Skip to content

유닛테스트

dong-yxxn edited this page Nov 15, 2024 · 12 revisions

Video

테스트 시나리오

  • VideoRepository Test
    • 공통 조건 ( Entity 설정 값 )
      • Place : place1, place2
      • Influencer : influencer1, influencer2
      • Video : video1, video2, video3, … , outBoundaryVideo, video12, video13
        • ( video11 → outBoundaryVideo )
      • 각 엔티티 연관 관계
        • video 1 ~ 5 : place1, influencer1
        • video 6 ~ 10 : place2, influencer2
        • video 11 : null, influencer1
        • video 12 : null, influencer2
        • outBoundaryVideo : place2, influencer2
    • findTop10ByInfluencerIdIn 메서드 동작에 대한 테스트
      • 정상 값 테스트
        • 입력 값 : influencerIds = { 1L } / pageable = { page = 0, size = 10 }
        • 예상 결과 값 : videos = { video5, video4, … , video1 }
        • 결과 확인 방법 : videos의 크기 확인 및, 내용을 순차적으로 id를 이용하여 확인
      • 최대 경계 값 테스트
        • 입력 값 : influencerIds = { 1L, 2L } / pageable = { page = 0, size = 10 }
        • 예상 결과 값 : videos = { outBoundaryVideo, video10, … , video2 }
        • 결과 확인 방법 : videos의 크기 확인 및, 내용을 순차적으로 id를 이용하여 확인
      • 최소 경계 값 테스트
        • 입력 값 : influencerIds = { } / pageable = { page = 0, size = 10 }
        • 예상 결과 값 : videos = { }
        • 결과 확인 방법 : videos의 크기 확인
    • findTop10ByOrderByIdDesc 메서드 동작에 대한 테스트
      • 입력 값 : pageable = { page = 0, size = 10 }
      • 예상 결과 값 : videos = { outBoundaryVideo, video10, … , video2 }
      • 결과 확인 방법 : videos의 크기 확인 및, 내용을 순차적으로 id를 이용하여 확인
    • findAllByPlaceIsNull 메서드 동작에 대한 테스트
      • 입력 값 : pageable = { page = 0, size = 10 }
      • 예상 결과 값 : videos = { video12, video13 }
      • 결과 확인 방법 : videos의 크기 확인 및 place가 null인지 확인
    • findTopByPlaceOrderByIdDesc 메서드 동작에 대한 테스트
      • 입력 값 : place = place1
      • 예상 결과 값 : videos = { video5 }
      • 결과 확인 방법 : id가 가장 큰 값이 반환되는 지 확인
    • findByPlaceIdIn 메서드 동작에 대한 테스트
      • 정상 값 테스트
        • 입력 값 : placeIds = { 1L }
        • 예상 결과 값 : videos = { video1, video2, … , video5 }
        • 결과 확인 방법 : videos의 크기 확인 및, 내용을 순차적으로 id를 이용하여 확인
      • 최대 경계 값 테스트
        • 입력 값 : placeIds= { 1L, 2L }
        • 예상 결과 값 : videos = { video1, video2, … , video11 }
        • 결과 확인 방법 : videos의 크기 확인 및, 내용을 순차적으로 id를 이용하여 확인
      • 최소 경계 값 테스트
        • 입력 값 : placeIds = { } / pageable = { page = 0, size = 10 }
        • 예상 결과 값 : videos = { }
        • 결과 확인 방법 : videos의 크기 확인
    • findByPlaceId 메서드 동작에 대한 테스트
      • 입력 값 : place = 1L
      • 예상 결과 값 : videos = { video1, video2, … ,video5 }
      • 결과 확인 방법 : videos의 크기 확인 및, 내용을 순차적으로 id를 이용하여 확인
    • findTop10ByOrderByViewCountIncreaseDesc 메서드 동작에 대한 테스트
      • 입력 값 : pageable = { page = 0, size = 10 }
      • 예상 결과 값 : videos = { outBoundaryVideo, video10, … ,video2 }
      • 결과 확인 방법 : videos의 크기 확인 및, 내용을 순차적으로 id를 이용하여 확인
        • 위와 같이 나오는 이유 : 조회수 업데이트를 for 문을 통해 수행하여서 id와 동일한 값을 지님
  • VideoService Test
    • getVideosBySurround 메서드에 대한 테스트
      • Mock
        • placeRepository.findPlacesByDistanceAndFilters
          • 입력 값 : videoSearchParam +

                         CategoryFilter(null) + 
            
                         Influencer(null) +
            
                         pageable(page=0, size=10)
            
          • 반환 값 : (Page) places = { place1, place2 }

        • videoRepository.findTopByPlaceOrderByIdDesc
          • 입력 값 : placeRepository.findPlacesByDistanceAndFilters 의 반환 값의 내용
          • 반환 값
            • place1 → video1
            • place2 → video2
      • 입력 값 : videoSearchParam = { “10.0”, “60.0”, “50.0”, “10.0”, “10.0”, “51.0” }
      • 예상 결과 값 : videoInfos = { videoInfo1, videoInfo2 }
      • 결과 확인 방법 : videos의 내용이 mock에 따른 반환 값인지 확인
    • getAllVideosDesc 메서드에 대한 테스트
      • Mock
        • videoRepository.findTop10ByOrderByIdDesc
          • 입력 값 : pageable(page=0, size=10)
          • 반환 값 : videos = { video2, video1 }
      • 입력 값 : x
      • 예상 결과 값 : videoInfos = { videoInfo2, videoInfo1 }
      • 결과 확인 방법 : videos의 내용이 mock에 따른 반환 값인지 확인
    • getVideosByMyInfluencer 메서드에 대한 테스트
      • Mock
        • videoRepository.findTop10ByInfluencerIdIn
          • 입력 값 : influencerIds(1L, 2L) +

                         pageable(page=0, size=10)
            
          • 반환 값 : videos = { video1, video2, video3 }

      • 입력 값 : influencerIds = { 1L , 2L }
      • 예상 결과 값 : videoInfos = { videoInfo1, videoInfo2, videoInfo3 }
      • 결과 확인 방법 : videos의 내용이 mock에 따른 반환 값인지 확인
    • getPlaceNullVideo 메서드에 대한 테스트
      • Mock
        • videoRepository.findAllByPlaceIsNull
          • 입력 값 : pageable(page=0, size=10)
          • 반환 값 : videos = { video2, video4 }
      • 입력 값 : pageable = { page = 0, size = 10 }
      • 예상 결과 값 : videoInfos = { videoInfo2, videoInfo4 }
      • 결과 확인 방법 : videos의 내용이 mock에 따른 반환 값인지 확인
    • getCoolVideo 메서드에 대한 테스트
      • Mock
        • videoRepository.findTop10ByOrderByIdDesc
          • 입력 값 : pageable(page=0, size=10)
          • 반환 값 : videos = { video2, video1 }
      • 입력 값 : x
      • 예상 결과 값 : videoInfos = { videoInfo2, videoInfo1 }

결과

  • Video Repository와 Service 테스트 결과, 모든 테스트 케이스 성공

    Repository Test 결과

    Service Test 결과


Place & LikedPlace

테스트 시나리오

  • PlaceRepository Test
    • 공통 조건

      • 테스트 장소 좌표
        • Place 1: (longitude: 10.0, latitude: 10.0), 관련 인플루언서: 성시경
        • Place 2: (longitude: 10.0, latitude: 50.0)
        • Place 3: (longitude: 10.0, latitude: 100.0)
        • Place 4: (longitude: 50.0, latitude: 50.0), 관련 인플루언서: 아이유
      • 테스트 기준 좌표
        • 테스트 좌표: (longitude: 10.0, latitude: 51.0)
      • 지도 범위(Boundary) 좌표
        • 좌상단: (longitude: 10.0, latitude: 60.0)
        • 우하단: (longitude: 50.0, latitude: 10.0)
      • 경계값 분석
        • 목적: Boundary 조건에 따라 Place 조회 기능이 의도대로 작동하는지 확인
        • Logitude (경도)
          • Left longitude of boundary = 10 → Longitude of Place 1, 2, 3 = 10
          • Right longitude of boundary = 50 → Longitude of Place 4 = 50
        • Latitude (위도)
          • Lower latitude of boundary = 10 → Latitude of Place 1 = 10
    • findPlacesByDistance 메서드 동작 테스트

      기준 좌표에서의 거리순으로 정렬하여 조회하는 메서드

      • Test 1: 거리 기반 장소 조회
        • 목적: 특정 좌표 기준으로 장소를 거리 순으로 조회
        • 입력 값:
          • longitude: "10.0"
          • latitude: "51.0"
          • pageable: PageRequest.of(0, 10)
        • 예상 결과:
          • places = { Place 2, Place 4, Place 1, Place 3 }
        • 검증 방법:
          • 조회된 결과의 크기 확인 (hasSize(4))
          • 결과 목록의 순서와 장소 이름 확인 (getName())
    • findPlacesByDistanceAndFilters 메서드 동작 테스트

      지도 범위(boundary) 좌표, 인플루언서, 카테고리 조건으로 필터링 후 거리순 정렬 및 페이지네이션 적용하여 장소 반환

      • Test 2: 필터링 없음 (Boundary만 적용)
        • 목적: 범위 조건만 적용하여 장소를 조회
        • 입력 값:
          • boundary: 좌상단 (10.0, 60.0), 우하단 (50.0, 10.0)
          • categories: null
          • influencers: null
          • pageable: PageRequest.of(0, 10)
        • 예상 결과:
          • places = { Place 2, Place 4, Place 1 }
          • 총 조회된 장소 개수: 3
        • 검증 방법:
          • 조회된 결과의 크기 확인 (hasSize(3))
          • 조회된 결과의 순서와 장소 이름 확인 (getName())
      • Test 3: 복합 카테고리 필터링 (CAFE, JAPANESE)
        • 목적: 특정 카테고리(CAFE, JAPANESE)로 필터링
        • 입력 값:
          • categories: ["CAFE", "JAPANESE"]
          • influencers: null
          • boundary: 동일
          • pageable: PageRequest.of(0, 10)
        • 예상 결과:
          • places = { Place 2, Place 4, Place 1 }
          • 각 장소의 카테고리는 각각 JAPANESE, JAPANESE, CAFE
        • 검증 방법:
          • 조회된 결과의 크기 확인 (hasSize(3))
          • 각 장소의 카테고리와 이름 확인 (getCategory(), getName())
      • Test 4: 단일 카테고리 필터링 (JAPANESE)
        • 목적: 특정 카테고리(JAPANESE)로 필터링
        • 입력 값:
          • categories: ["JAPANESE"]
          • influencers: null
          • 기타 동일
        • 예상 결과:
          • places = { Place 2, Place 4 }
          • 각 장소의 카테고리는 모두 JAPANESE
        • 검증 방법
          • 조회된 결과의 크기 확인 (hasSize(2))
          • 각 장소의 카테고리와 이름 확인 (getCategory(), getName())
      • Test 5: 인플루언서 필터링 (성시경, 아이유)
        • 목적: 특정 인플루언서(성시경, 아이유)로 필터링
        • 입력 값:
          • categories: null
          • influencers: ["성시경", "아이유"]
          • 기타 동일
        • 예상 결과:
          • places = { Place 4, Place 1 }
        • 검증 방법:
          • 조회된 결과의 크기 확인 (hasSize(2))
          • 각 장소의 이름 확인 (getName())
      • Test 6: 인플루언서 필터링 (성시경)
        • 목적: 특정 인플루언서(성시경)로 필터링
        • 입력 값:
          • categories: null
          • influencers: ["성시경"]
          • 기타 동일
        • 예상 결과:
          • places = { Place 1 }
        • 검증 방법:
          • 조회된 결과의 크기 확인 (hasSize(1))
          • 장소의 이름 확인 (getName() )
      • Test 7: 카테고리(JAPANESE), 인플루언서(아이유) 필터링
        • 목적: 특정 카테고리(JAPANESE)와 특정 인플루언서(아이유) 조건을 모두 만족하는 장소 필터링
        • 입력 값:
          • categories: ["JAPANESE"]
          • influencers: ["아이유"]
          • 기타 동일
        • 예상 결과:
          • places = { Place 4 }
        • 검증 방법:
          • 조회된 결과의 크기 확인 (hasSize(1))
          • 장소의 이름과 카테고리 확인 (getName(), getCategory())
      • Test 8: 페이징 테스트 (page=1, size=2)
        • 목적: 페이징을 적용하여 boundary 내 장소 조회
        • 입력 값:
          • boundary: 동일
          • categories: null
          • influencers: null
          • pageable: PageRequest.of(1, 2)
        • 예상 결과:
          • totalElements = 3
          • totalPages = 2
          • places = { Place 1 }
        • 검증 방법:
          • getTotalElements() == 3
          • getTotalPages() == 2
          • 조회된 결과의 크기와 장소 이름 확인 (hasSize(1), getName())
  • LikedPlaceRepository Test
    • 공통 조건

      • User 정보
        • user1: (username: “user1”, nickname: “nick1”, UserType: KAKAO, Role: USER)
      • Place 정보
        • place1: (name: “Place 1”, category: 카페, 좌표: (longitude: 10.0, latitude: 10.0))
    • findByUserAndPlaceId 메서드 동작 테스트

      user_id, place_id로 LikedPlace를 조회하는 메서드

      • Test 1: LikedPlace 조회
        • 목적: user_id와 place_id로 LikedPlace를 제대로 조회하는지 확인
        • 사전 조건:
          • LikedPlace 엔티티가 존재 (LikedPlace(user1, place1))
        • 예상 결과:
          • 반환된 LikedPlace의 유저와 장소 정보가 각각 user1와 place1과 일치
        • 검증 방법:
          • assertThat(actual).isPresent()로 결과가 존재하는지 확인.
          • 반환된 LikedPlace의 user와 place의 이름이 각각 user1와 place1의 이름과 일치하는지 확인 getName()
          • 반환된 LikedPlace의 isLiked 값이 default인 false인지 확인 (isFalse())
      • Test 2: 장소 좋아요 및 isLiked 상태 업데이트
        • 목적: 기존의 LikedPlace의 좋아요 상태를 업데이트하는 기능 검증
        • 사전 조건:
          • 초기 LikedPlace의 isLiked 값은 false
        • 예상 결과:
          • updateLike(true)를 호출한 후 isLiked 값이 true로 변경
        • 검증 방법:
          • 초기 isLiked 상태 확인 (isFalse())
          • true로 상태 업데이트 (updateLike(true))
          • 업데이트된 LikedPlace의 isLiked 값이 true인지 확인 (isTrue())
  • PlaceService Test
    • getPlacesWithinRadius 메서드에 대한 테스트

      필터링 후 사용자 위치 기준으로 장소를 거리순으로 정렬 후 반환하는 메서드

      • 필터링없이 거리순 반환

        Mock

        • placeRepository.findPlacesByDistanceAndFilters
          • 입력 값: 좌표 및 boundary 정보
          • 반환 값: PageImpl(List.of(place2, place4, place1))
        • videoRepository.findByPlaceIdIn
          • 입력 값: placeIds = {place2.id, place4.id, place1.id}
          • 반환 값: List.of(video1, video2, video3)
        • AuthorizationUtil.getUsername
          • 입력 값: 없음
          • 반환 값: null
        • 입력 값: 좌표: (10.0, 51.0), Boundary: [(10.0, 60.0), (50.0, 10.0)], page=0, size=10
        • 예상 결과 값:
          • PlaceInfos = { “Place 2”, “Place 4”, “Place 1” }
        • 각 장소의 인플루언서 정보:
          • “Place 2”: 없음
          • “Place 4”: “아이유”
          • “Place 1”: “성시경”
        • 결과 확인 방법:
          • 반환된 PlaceInfos의 크기와 내용이 Mock 반환 값과 일치하는지 검증
      • 복합 카테고리 필터링(일식, 카페)

        Mock

        • placeRepository.findPlacesByDistanceAndFilters
          • 입력 값: 카테고리 필터 및 좌표 정보
          • 반환 값: PageImpl(List.of(place2, place4, place1))
        • videoRepository.findByPlaceIdIn
          • 입력 값: placeIds = {place2.id, place4.id, place1.id}
          • 반환 값: List.of(video1, video2, video3)
        • AuthorizationUtil.getUsername
          • 입력 값: 없음
          • 반환 값: null
        • 입력 값: Categories = [“일식”, “카페”], page=0, size=10
        • 예상 결과 값:
          • PlaceInfos = { “Place 2”, “Place 4”, “Place 1” }
        • 각 장소의 카테고리:
          • “Place 2”: “일식”
          • “Place 4”: “일식”
          • “Place 1”: “카페”
        • 결과 확인 방법:
          • 반환된 PlaceInfos의 크기와 각 장소의 카테고리가 Mock 반환 값과 일치하는지 검증
      • 단일 카테고리 필터링 (일식)

        Mock

        • placeRepository.findPlacesByDistanceAndFilters
          • 입력 값: 카테고리 필터 및 좌표 정보
          • 반환 값: PageImpl(List.of(place2, place4))
        • videoRepository.findByPlaceIdIn
          • 입력 값: placeIds = {place2.id, place4.id}
          • 반환 값: List.of(video2, video3)
        • AuthorizationUtil.getUsername
          • 입력 값: 없음
          • 반환 값: null
        • 입력 값: Categories = [“일식”], page=0, size=10
        • 예상 결과 값:
          • PlaceInfos = { “Place 2”, “Place 4” }
        • 각 장소의 카테고리:
          • “Place 2”: “일식”
          • “Place 4”: “일식”
        • 결과 확인 방법:
          • 반환된 PlaceInfos의 크기와 각 장소의 카테고리가 Mock 반환 값과 일치하는지 검증
      • 복합 인플루언서 필터링(아이유, 성시경)

        Mock

        • placeRepository.findPlacesByDistanceAndFilters
          • 입력 값: 인플루언서 필터 및 좌표 정보
          • 반환 값: PageImpl(List.of(place4, place1))
        • videoRepository.findByPlaceIdIn
          • 입력 값: placeIds = {place4.id, place1.id}
          • 반환 값: List.of(video1, video2, video3)
        • AuthorizationUtil.getUsername
          • 입력 값: 없음
          • 반환 값: null
        • 입력 값: Influencers = [“아이유”, “성시경”], page=0, size=10
        • 예상 결과 값:
          • PlaceInfos = { “Place 4”, “Place 1” }
        • 각 장소의 인플루언서:
          • “Place 4”: “아이유”
          • “Place 1”: “성시경”
        • 결과 확인 방법:
          • 반환된 PlaceInfos의 크기와 각 장소의 인플루언서 정보가 Mock 반환 값과 일치하는지 검증
      • 단일 인플루언서 필터링(아이유)

        Mock

        • placeRepository.findPlacesByDistanceAndFilters
          • 입력 값: 인플루언서 필터 및 좌표 정보
          • 반환 값: PageImpl(List.of(place4))
        • videoRepository.findByPlaceIdIn
          • 입력 값: placeIds = {place4.id}
          • 반환 값: List.of(video2)
        • AuthorizationUtil.getUsername
          • 입력 값: 없음
          • 반환 값: null
        • 입력 값: Influencers = [“아이유”], page=0, size=10
        • 예상 결과 값:
          • PlaceInfos = { “Place 4” }
          • 인플루언서: “아이유”
        • 결과 확인 방법:
          • 반환된 PlaceInfos 크기가 1인지 확인
          • Place 4는 “아이유”와 연결되어 있는지 검증
      • 카테고리(일식) + 인플루언서(아이유, 성시경) 필터링

        Mock

        • placeRepository.findPlacesByDistanceAndFilters
          • 입력 값: 카테고리와 인플루언서 필터
          • 반환 값: PageImpl(List.of(place4))
        • videoRepository.findByPlaceIdIn
          • 입력 값: placeIds = {place4.id}
          • 반환 값: List.of(video2)
        • AuthorizationUtil.getUsername
          • 입력 값: 없음
          • 반환 값: null
        • 입력 값: Categories = [“일식”], Influencers = [“아이유”, “성시경”], page=0, size=10
        • 예상 결과 값:
          • PlaceInfos = { “Place 4” }
          • 카테고리: “일식”
          • 인플루언서: “아이유”
        • 결과 확인 방법:
          • 반환된 PlaceInfos 크기가 1인지 확인
          • Place 4는 “아이유”와 연결되고, 카테고리가 “일식”인지 검증
      • user2 로그인, 인플루언서(아이유, 성시경) 필터링

        Mock

        • AuthorizationUtil.getUserId
          • 입력 값: 없음
          • 반환 값: 2L
        • placeRepository.findPlacesByDistanceAndFilters
          • 입력 값: 좌표 및 인플루언서 필터
          • 반환 값: PageImpl(List.of(place4, place1))
        • videoRepository.findByPlaceIdIn
          • 입력 값: {place4.id, place1.id}
          • 반환 값: {video1, video2, video3}
        • likedPlaceRepository.findByUserIdAndPlaceId
          • 입력 값: (2L, place4.id)
          • 반환 값: Optional.empty()
        • 입력 값:
          • influencers=["아이유", "성시경"]
          • userId=2L
        • 예상 결과 값:
          • PlaceInfos: [“Place 4”, “Place 1”]
          • 좋아요 상태: false
          • 관련 인플루언서: “아이유”, “성시경”
        • 결과 확인 방법:
          • 반환된 PlaceInfos 크기가 2인지 확인
          • Place 4는 “아이유”, Place 1은 “성시경”과 연결되고, 좋아요 상태가 false인지 검증
      • user2 로그인, place4 좋아요, 인플루언서(아이유, 성시경) 필터링

        Mock

        • AuthorizationUtil.getUserId
          • 입력 값: 없음
          • 반환 값: 2L
        • placeRepository.findPlacesByDistanceAndFilters
          • 입력 값: 좌표 및 인플루언서 필터
          • 반환 값: PageImpl(List.of(place4, place1))
        • videoRepository.findByPlaceIdIn
          • 입력 값: {place4.id, [place1.id](http://place1.id/)}
          • 반환 값: {video1, video2, video3}
        • likedPlaceRepository.findByUserIdAndPlaceId
          • 입력 값: (2L, place4.id)
          • 반환 값: Optional.empty()
        • userRepository.findById
          • 입력 값: 2L
          • 반환 값: Optional.of(user2)
        • placeRepository.findById
          • 입력 값: place4.id
          • 반환 값: Optional.of(place4)
        • likedPlaceRepository.save
          • 입력 값: new LikedPlace
          • 반환 값: 저장된 LikedPlace
        • 입력 값:
          • influencers=["아이유", "성시경"]
          • place4 좋아요
          • userId=2L
        • 예상 결과 값:
          • PlaceInfos: [“Place 4”, “Place 1”]
          • Place4 좋아요 상태: true
          • 관련 인플루언서: “아이유”, “성시경”
        • 결과 확인 방법:
          • 반환된 PlaceInfos 크기가 2인지 확인
          • Place 4는 “아이유”와 연결되고 좋아요 상태가 true인지, Place 1은 “성시경”과 연결되고, 좋아요 상태가 false 인지 검증
    • getPlaceDetailInfo 메서드에 대한 테스트

      장소 세부정보를 반환하는 메서드

      • 장소 세부정보 조회 (로그아웃 상태)

        Mock

        • placeRepository.findById
          • 입력 값: place4.id
          • 반환 값: Optional.of(place4)
        • videoRepository.findByPlaceId
          • 입력 값: place4.id
          • 반환 값: [video2, video3]
        • reviewRepository.countByPlaceIdAndIsLikedTrue
          • 입력 값: place4.id
          • 반환 값: 2
        • reviewRepository.countByPlaceIdAndIsLikedFalse
          • 입력 값: place4.id
          • 반환 값: 1
        • AuthorizationUtil.getUsername
          • 입력 값: 없음
          • 반환 값: null
        • 입력 값: placeId=4
        • 예상 결과 값:
          • PlaceDetailInfo:
            • Likes: false
            • 좋아요 수: 2
            • 싫어요 수: 1
          • 관련 인플루언서: “아이유”
        • 결과 확인 방법:
          • 반환된 PlaceDetailInfo의 좋아요, 싫어요 수와 관련 인플루언서 정보 확인
      • user1 로그인, 장소 세부정보 조회

        Mock

        • AuthorizationUtil.getUserId
          • 입력 값: 없음
          • 반환 값: 1L
        • placeRepository.findById
          • 입력 값: place4.id
          • 반환 값: Optional.of(place4)
        • videoRepository.findByPlaceId
          • 입력 값: place4.id
          • 반환 값: [video2, video3]
        • reviewRepository.countByPlaceIdAndIsLikedTrue
          • 입력 값: place4.id
          • 반환 값: 2
        • reviewRepository.countByPlaceIdAndIsLikedFalse
          • 입력 값: place4.id
          • 반환 값: 1
        • 입력 값: placeId=4
        • 예상 결과 값:
          • PlaceDetailInfo:
            • 좋아요 상태: false
            • 좋아요 수: 2
            • 싫어요 수: 1
        • 관련 인플루언서: “아이유”
        • 결과 확인 방법:
          • 반환된 PlaceDetailInfo의 좋아요, 싫어요 수와 관련 인플루언서 정보가 예상 값과 일치하는지 검증
      • user1 로그인, place4 좋아요, 장소 세부정보 조회

        Mock

        • AuthorizationUtil.getUserId
          • 입력 값: 없음
          • 반환 값: 1L
        • placeRepository.findById
          • 입력 값: place4.id
          • 반환 값: Optional.of(place4)
        • userRepository.findById
          • 입력 값: user1.id
          • 반환 값: Optional.of(user1)
        • videoRepository.findByPlaceId
          • 입력 값: place4.id
          • 반환 값: [video2, video3]
        • likedPlaceRepository.findByUserIdAndPlaceId
          • 입력 값: (user1.id, place4.id)
          • 반환 값: Optional.empty()
        • reviewRepository.countByPlaceIdAndIsLikedTrue
          • 입력 값: place4.id
          • 반환 값: 2
        • reviewRepository.countByPlaceIdAndIsLikedFalse
          • 입력 값: place4.id
          • 반환 값: 1
        • 입력 값:
          • placeId=4
          • place4 좋아요
        • 예상 결과 값:
          • PlaceDetailInfo:
            • 좋아요 상태: true
            • 좋아요 수: 2
            • 싫어요 수: 1
            • 관련 인플루언서: “아이유”
        • 결과 확인 방법:
          • PlaceDetailInfo의 좋아요 상태가 true로 변경되었는지 확인
          • 관련 좋아요 및 싫어요 수가 예상 값과 일치하는지 확인
    • likeToPlace 메서드에 대한 테스트

      사용자가 장소에 좋아요한 정보를 저장하거나 업데이트하는 메서드

      • 장소 좋아요 추가 및 업데이트

        Mock

        • AuthorizationUtil.getUserId
          • 입력 값: 없음
          • 반환 값: 1L
        • likedPlaceRepository.findByUserIdAndPlaceId
          • 입력 값: (1L, place1.id)
          • 반환 값: Optional.of(likedPlace1)
        • likedPlaceRepository.save
          • 입력 값: 업데이트된 LikedPlace
          • 반환 값: 저장된 LikedPlace
        • 입력 값:
          • placeId=1
          • liked=true
        • 예상 결과 값:
          • LikedPlace 상태: true
        • 결과 확인 방법:
          • 저장된 LikedPlace의 상태가 true로 업데이트되었는지 확인
          • likedPlaceRepository.save()가 호출되었는지 검증
      • 좋아요한 장소 취소하기

        Mock

        • AuthorizationUtil.getUserId
          • 입력 값: 없음
          • 반환 값: 1L (user1의 ID)
        • likedPlaceRepository.findByUserIdAndPlaceId
          • 입력 값 1: (1L, place1.id) (초기 좋아요 상태)
          • 반환 값 1: Optional.of(LikedPlace(user1, place1, true)) (Place 1을 좋아요한 상태)
          • 입력 값 2: (1L, place1.id) (좋아요 취소)
          • 반환 값 2: Optional.of(LikedPlace(user1, place1, false)) (좋아요가 취소된 상태)
        • likedPlaceRepository.save
          • 입력 값: LikedPlace 객체
          • 동작: 저장된 LikedPlace의 상태를 업데이트 (좋아요 상태 변경)
        • 입력 값:
          • Command 1: PlaceLikeCommand(place1.id, true) (좋아요 추가)
          • Command 2: PlaceLikeCommand(place1.id, false) (좋아요 취소)
        • 예상 결과 값:
          • LikedPlace 상태:
            • Command 1 실행 후: 좋아요 상태 true
            • Command 2 실행 후: 좋아요 상태 false
        • 결과 확인 방법:
          1. 좋아요 추가:
            • placeService.likeToPlace(command1) 호출 후, LikedPlace가 저장되었는지 검증 (likedPlaceRepository.save 호출 횟수 확인).
            • likedPlaceRepository.findByUserIdAndPlaceId(1L, place1.id) 호출 결과 좋아요 상태가 true인지 확인.
          2. 좋아요 취소:
            • placeService.likeToPlace(command2) 호출 후, LikedPlace가 저장되었는지 검증 (likedPlaceRepository.save 호출 횟수 확인).
            • likedPlaceRepository.findByUserIdAndPlaceId(1L, place1.id) 호출 결과 좋아요 상태가 false인지 확인.

결과

  • PlaceRepository, LikedPlaceRepository와 PlaceService 테스트 결과, 모든 테스트 케이스 성공

    PlaceRepository Test 결과

    • image

    LikedPlaceRepository Test 결과

    • image (1)

    PlaceService Test 결과

    • image (2)

Influencer Domain

테스트 시나리오

  • InfluencerRepositoryTest
    • findAll 메서드에 대한 테스트
      • Mock: 없음 (실제 influencerRepository 사용)
      • 입력 값:
        • 새로운 Influencer 객체 2개 생성:
          • influencer4 = Influencer("influencer4", "imgUrl1", "job1")
          • influencer5 = Influencer("influencer5", "imgUrl2", "job2")
        • influencerRepository.save(influencer4)
        • influencerRepository.save(influencer5)
      • 예상 결과 값: savedInfluencers 리스트의 첫 번째 요소가 influencer4, 두 번째 요소가 influencer5와 같음
      • 결과 확인 방법:
        • savedInfluencers.get(0)influencer4가 재귀적으로 비교했을 때 일치하는지 확인.
        • savedInfluencers.get(1)influencer5가 재귀적으로 비교했을 때 일치하는지 확인.
  • InfluencerServiceTest
    • getAllInfluencer 메서드에 대한 테스트

      1. 로그인 상태가 아닐 때

        • Mock
          • influencerRepository.findAll
            • 입력 값: PageRequest.of(0, 10)
            • 반환 값: PageImpl(List.of(influencer1, influencer2))
          • AuthorizationUtil.getUserId
            • 입력 값: 없음
            • 반환 값: null
        • 입력 값: Pageable = PageRequest.of(0, 10)
        • 예상 결과 값: influencerInfoPage.size = 2, 첫 번째와 두 번째 InfluencerInfoinfluencerName이 각각 "influencer1", "influencer2"이며 likesfalse
        • 결과 확인 방법:
          • influencerService.getAllInfluencers(pageable) 호출 후 반환된 influencerInfoPage의 크기가 2인지 확인.
          • InfluencerInfo 객체의 influencerName이 원래 Influencer 객체의 name과 일치하고 likesfalse인지 검증.
      2. 로그인 상태일 때

      • Mock
        • influencerRepository.findAll
          • 입력 값 : PageRequest.of(0, 10)
          • 반환 값 : PageImpl(List.of(influencer1, influencer2, influencer3))
            • 반환 값 : userId = 1L
        • AuthorizationUtil.getUserId
          • 입력 값: 없음
          • 반환 값: 1L
        • favoriteInfluencerRepository.findLikedInfluencerIdsByUserId
          • 입력 값 : userId = 1L
          • 반환 값 : Set.of(2L, 3L) (좋아요를 누른 인플루언서 ID)
      • 입력 값 : Pageable = PageRequest.of(0, 10)
      • 예상 결과 값 : influencerInfoPage.size = 3, 각 InfluencerInfo 객체의 likes 와 순서가 아래와 같음.
        • influencer2: likes = true
        • influencer3: likes = true
        • influencer1: likes = false
      • 결과 확인 방법 :
        • influencerService.getAllInfluencers(pageable) 호출 후 반환된 influencerInfoPage의 크기가 3인지 확인.
        • 두 번째, 세 번째 InfluencerInfo 객체의 likestrue, 첫 번째 객체의 likesfalse인지 검증.
    • createInfluencer 메서드에 대한 테스트

      • Mock
      • influencerRepository.save
      • 입력 값: InfluencerCommand(name="name", imgUrl="imgUrl", job="job")
      • 반환 값: Influencer(id=1L, name="name", imgUrl="imgUrl", job="job")
      • 입력 값: InfluencerCommand = { name="name", imgUrl="imgUrl", job="job" }
      • 예상 결과 값: savedId = 1L
      • 결과 확인 방법:
        • influencerService.createInfluencer(command)를 호출하여 반환 값이 1L과 일치하는지 확인.
    • updateInfluencer 메서드에 대한 테스트

      • Mock
        • influencerRepository.findById
          • 입력 값: 1L
          • 반환 값: Optional.of(Influencer(id=1L, name="name", imgUrl="imgUrl", job="job"))
      • 입력 값: id = 1L, InfluencerCommand = { name="updatedName", imgUrl="updatedImgUrl", job="updatedJob" }
      • 예상 결과 값: updatedId = 1L, Influencer 객체의 필드가 updatedName, updatedImgUrl, updatedJob으로 업데이트됨
      • 결과 확인 방법:
        • influencerService.updateInfluencer(1L, command)를 호출하여 반환 값이 1L과 일치하는지 확인.
        • 반환된 Influencer 객체의 name, imgUrl, job 필드가 각각 updatedName, updatedImgUrl, updatedJob으로 업데이트되었는지 검증.
    • deleteInfluencer 메서드에 대한 테스트

      • Mock
        • influencerRepository.findById
          • 입력 값 : id = 1L
          • 반환 값 : Optional.of(Influencer(id=1L, name="name", imgUrl="imgUrl", job="job"))
      • 입력 값 : id = 1L
      • 예상 결과 값 : influencerRepository.deleteinfluencer 객체와 함께 한 번 호출됨
      • 결과 확인 방법 :
        • influencerService.deleteInfluencer(1L)를 호출하여 influencerRepository.delete() 메서드가 한 번 호출되는지 검증.
  • InfluencerControllerTest
    • getAllInfluencers 메서드에 대한 테스트
      • Mock
        • influencerService.getAllInfluencers
          • 입력 값 : PageRequest.of(0, 10)
          • 반환 값 : PageImpl(List.of(influencer1, influencer2))
      • 입력 값 : Pageable = PageRequest.of(0, 10)
      • 예상 결과 값 : InfluencerResponse = { influencerResponse1, influencerResponse2 }
      • 결과 확인 방법 :
        • mockMvc.perform()을 통해 API 호출 후 반환된 JSON 값이 mock에 따른 예상값과 일치하는지 확인.
        • influencerService.getAllInfluencers(pageable) 메서드가 한 번 호출되는지 검증.

결과

  • InfluencerRepositoryTest
    image

  • InfluencerServiceTest
    image

  • InfluencerControllerTest
    image

FavoriteInfluencer Domain

테스트 시나리오

  • FavoriteInfluencerServiceTest
    • getFavoriteInfluencers 메서드에 대한 테스트
      • Mock
        • favoriteRepository.findByUserIdAndIsLikedTrue
          • 입력 값: userId = 1L, pageable = PageRequest.of(0, 10)
          • 반환 값: PageImpl(List.of(favoriteInfluencer1))
      • 입력 값:
        • userId = 1L
        • pageable = PageRequest.of(0, 10)
      • 예상 결과 값:
        • result.size = 1
        • InfluencerInfo 객체의 influencerName"influencer1"
        • InfluencerInfo 객체의 likestrue
      • 결과 확인 방법:
        • Repository의 메서드 호출 검증
        • 반환된 Page 객체의 첫 번째 요소가 InfluencerInfo 타입인지 검증
        • InfluencerInfo 객체의 influencerName이 예상값과 일치하는지 검증
        • InfluencerInfo 객체의 likes 필드가 true인지 검증

결과

  • FavoriteInfluencerServiceTest image

Review Domain

테스트 시나리오

  • ReviewServiceTest
    • createReview 메서드에 대한 테스트 시나리오

      1. 정상 테스트

        • Mock
          • AuthorizationUtil.getUserId
            • 입력 값: 없음
            • 반환 값: userId = 1L
          • currentUserProvider.getCurrentUser
            • 입력 값: 없음
            • 반환 값: userMock (userId = 1L)
          • placeRepository.findById
            • 입력 값: placeId = 1L
            • 반환 값: Optional.of(place)
          • reviewRepository.existsByUserIdAndPlaceId
            • 입력 값: userId = 1L, placeId = 1L
            • 반환 값: false
        • 입력 값: placeId = 1L, command = new ReviewCommand(true, "comment")
        • 예상 결과 값: 예외 없이 리뷰가 생성됨
        • 결과 확인 방법:
          • reviewService.createReview(placeId, command) 호출 시 예외가 발생하지 않는지 확인.
          • reviewRepository.save 메서드가 호출되었는지 검증.
      2. 이미 해당 장소에 리뷰가 있을 때

        • Mock
          • AuthorizationUtil.getUserId
            • 입력 값: 없음
            • 반환 값: userId = 1L
          • currentUserProvider.getCurrentUser
            • 입력 값: 없음
            • 반환 값: userMock (userId = 1L)
          • placeRepository.findById
            • 입력 값: placeId = 1L
            • 반환 값: Optional.of(place)
          • reviewRepository.existsByUserIdAndPlaceId
            • 입력 값: userId = 1L, placeId = 1L
            • 반환 값: true
        • 입력 값: placeId = 1L, command = new ReviewCommand(true, "comment")
        • 예상 결과 값: InplaceException 발생, 에러 메시지는 REVIEW_ALREADY_EXISTS
        • 결과 확인 방법:
          • reviewService.createReview(placeId, command) 호출 시 InplaceException이 발생하는지 확인.
          • 발생한 예외의 메시지가 REVIEW_ALREADY_EXISTS와 일치하는지 검증.
    • getReviews 메서드에 대한 테스트

      1. 로그인 상태일 때

        • Mock
          • AuthorizationUtil.getUserId
            • 입력 값: 없음
            • 반환 값: 1L
          • reviewRepository.findByPlaceId
            • 입력 값: placeId = 1L, pageable = PageRequest.of(0, 10)
            • 반환 값: PageImpl(List.of(review))
          • userMock.getId
            • 입력 값: 없음
            • 반환 값: 1L
        • 입력 값: placeId = 1L, pageable = PageRequest.of(0, 10)
        • 예상 결과 값: reviewInfoPage.size = 1, ReviewInfominetrue
        • 결과 확인 방법:
          • ReviewInfo 객체의 comment , mine 필드의 값이 comment , true인지 검증.
      2. 로그인하지 않은 상태에서 리뷰 조회

        • Mock
          • AuthorizationUtil.isNotLoginUser
            • 입력 값: 없음
            • 반환 값: true
          • reviewRepository.findByPlaceId
            • 입력 값: placeId = 1L, pageable = PageRequest.of(0, 10)
            • 반환 값: PageImpl(List.of(review))
        • 입력 값: placeId = 1L, pageable = PageRequest.of(0, 10)
        • 예상 결과 값: reviewInfoPage.size = 1, ReviewInfominefalse
        • 결과 확인 방법:
          • ReviewInfo 객체의 comment , mine 필드의 값이 comment , false인지 검증.
    • deleteReview 메서드에 대한 테스트

      • 리뷰 작성자가 아닌 사용자가 삭제를 요청할 때
        • Mock
          • AuthorizationUtil.getUserId
            • 입력 값: 없음
            • 반환 값: userId2 = 2L
          • reviewRepository.findById
            • 입력 값: reviewId = 1L
            • 반환 값: Optional.of(review)
          • userMock.getId
            • 입력 값: 없음
            • 반환 값: 1L
        • 입력 값: reviewId = 1L
        • 예상 결과 값: InplaceException 발생, 에러 메시지는 NOT_OWNER
        • 결과 확인 방법:
          • reviewService.deleteReview(reviewId) 호출 시 InplaceException이 발생하는지 확인.
          • 발생한 예외의 메시지가 NOT_OWNER와 일치하는지 검증.
    • getMyReviews 메서드에 대한 테스트

      • Mock
        • reviewRepository.findByUserIdWithPlace
          • 입력 값: userId = 1L, pageable = PageRequest.of(0, 10)
          • 반환 값: PageImpl(List.of(myReview))
      • 입력 값:
        • userId = 1L
        • pageable = PageRequest.of(0, 10)
      • 예상 결과 값:
        • result.size = 1
        • MyReviewInfo 객체의 comment가 리뷰의 comment와 일치
        • MyReviewInfo 객체의 placeInfo.placeName이 장소의 이름과 일치
      • 결과 확인 방법:
        • Repository의 메서드 호출 검증
        • 반환된 Page 객체의 첫 번째 요소가 MyReviewInfo 타입인지 검증
        • MyReviewInfo 객체의 comment가 예상값과 일치하는지 검증
        • MyReviewInfo 객체의 placeInfo.placeName이 예상값과 일치하는지 검증
  • ReviewRepositoryTest
    • countByPlaceIdAndIsLikedTrue/False 메서드 테스트

      좋아요 및 비추천 카운트 테스트

      • 초기 데이터:
        • Place: place1
        • User: user1, user2, user3, user4
        • Review:
          • Review 1: User 1 → Place 1, isLiked = true
          • Review 2: User 2 → Place 1, isLiked = true
          • Review 3: User 3 → Place 1, isLiked = false
          • Review 4: User 4 → Place 1, isLiked = true
      • 입력 값:
        • Place ID: 1L
      • 예상 결과 값:
        • 좋아요(isLiked == true)의 개수: 3
        • 비추천(isLiked == false)의 개수: 1
      • 결과 확인 방법:
        • reviewRepository.countByPlaceIdAndIsLikedTrue(1L) 호출 결과가 3인지 확인.
        • reviewRepository.countByPlaceIdAndIsLikedFalse(1L) 호출 결과가 1인지 확인.

결과

  • ReviewServiceTest image

  • ReviewRepositoryTest image