• 카테고리

    질문 & 답변
  • 세부 분야

    백엔드

  • 해결 여부

    미해결

postService 목록 조회 단위 테스트

22.10.26 14:01 작성 조회수 298

0

  • 당연히 구글링 해보셨져? 원하는 결과를 못찾으셨나요? 어떤 검색어를 입력했는지 알려주세

  • 문제가 발생한 코드(프로젝트)를 Github에 올리시고 링크를 알려주세요.

 

안녕하세요. 호돌맨님.

postService에서 목록 조회하는 단위테스트에 대해서 질문이 있습니다.

 

먼저 목록 조회 코드부터 보여드리면

postService.findPosts 는 postQueryRepository에 구현체로 만들었습니다.

  • postService

@Slf4j
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class PostService {

    public static final String ENTITY_NAME = "post";

    private final PostQueryRepository postQueryRepository;
    private final PostRepository postRepository;

    /**
     * Post 목록 조회
     */
    public Page<Post> findPosts(PostSearchCondition condition, Pageable pageable) {
        return postQueryRepository.findPosts(condition, pageable);
    }
}
  • postQueryRepository

@Repository
public class PostQueryRepository {

    private final JPAQueryFactory queryFactory;

    public PostQueryRepository(EntityManager em) {
        this.queryFactory = new JPAQueryFactory(em);
    }

    /**
     * Post 목록 조회
     */
    public Page<Post> findPosts(PostSearchCondition condition, Pageable pageable) {

        List<Post> content = getPostList(condition, pageable);

        JPAQuery<Long> count = getPostListCount(condition);

        return PageableExecutionUtils.getPage(content, pageable, count::fetchOne);
    }

    /**
     * Post 목록
     */
    private List<Post> getPostList(PostSearchCondition condition, Pageable pageable) {
        return queryFactory
                .select(post)
                .from(post)
                .where(
                        searchCondition(condition.getSearchCondition(), condition.getSearchKeyword())
                )
                .offset(pageable.getOffset())
                .limit(pageable.getPageSize())
                .orderBy(post.id.desc())
                .fetch();
    }

    /**
     * Post 목록 카운트
     */
    private JPAQuery<Long> getPostListCount(PostSearchCondition condition) {
        return queryFactory
                .select(post.count())
                .from(post)
                .where(
                        searchCondition(condition.getSearchCondition(), condition.getSearchKeyword())
                );
    }

    /**
     * where searchCondition LIKE '%searchKeyword%'
     */
    private BooleanExpression searchCondition(SearchCondition searchCondition, String searchKeyword) {
        if (searchCondition == null || !hasText(searchKeyword)) {
            return null;
        }

        if (SearchCondition.TITLE.equals(searchCondition)) {
            return post.title.contains(searchKeyword);
        } else if (SearchCondition.CONTENT.equals(searchCondition)) {
            return post.content.contains(searchKeyword);
        } else {
            return null;
        }
    }
}

 

다음은 테스트 코드입니다.

  • postServiceTest

@ExtendWith(MockitoExtension.class)
class PostServiceTest {

    //CREATE_POST
    public static final String POST_TITLE = "post_title";
    public static final String POST_CONTENT = "post_content";

    //UPDATE_POST
    public static final String UPDATE_TITLE = "update_title";
    public static final String UPDATE_CONTENT = "update_content";

    //ERROR_MESSAGE
    public static final String ENTITY_NAME = "post";
    public static final Long NOT_FOUND_ID = 1L;
    public static final String HAS_MESSAGE_STARTING_WITH = "존재하지 않는 ";
    public static final String HAS_MESSAGE_ENDING_WITH = "id = ";


    @InjectMocks PostService postService;

    @Mock PostQueryRepository postQueryRepository;

    @Mock PostRepository postRepository;

    private Post getPost(String title, String content) {
        return Post.createPostBuilder()
                .title(title)
                .content(content)
                .build();
    }

    @Test
    @DisplayName("post 목록 조회")
    void findPosts() {
        //given
        List<Post> posts = new ArrayList<>();
        for (int i = 0; i < 30; i++) {
            posts.add(getPost(POST_TITLE + i, POST_CONTENT));
        }

        //검색 안먹힘
        PostSearchCondition condition = new PostSearchCondition();
        condition.setSearchCondition(SearchCondition.TITLE);
        condition.setSearchKeyword("0");
        PageRequest pageRequest = PageRequest.of(0, 10);
        given(postQueryRepository.findPosts(condition, pageRequest)).willReturn(new PageImpl<>(posts));

        //when
        Page<Post> contents = postService.findPosts(condition, pageRequest);

        //then
        assertThat(contents.getTotalElements()).isEqualTo(3);
        assertThat(contents.getContent().size()).isEqualTo(3);
    }
}

 

여기서 findPosts 단위 테스트를 진행하려고 하는데요.

목록을 30개를 만들고 검색조건과 페이지 정보를 파라미터로 넘겨서 검색이 된 결과가 나올것이라고 예상했지만 검색조건은 먹히지 않고 30개의 목록만 리턴이 됩니다.

 

전 검색 조건대로 "0"들어간 title만 검색이되어서

contents.getTotalElements() == 3, contents.getcontent().size() == 3 으로 예상을 했는데

contents.getTotalElements() == 30, contents.getcontent().size() == 30 로 결과가 나와 테스트에 실패하게됩니다.

 

구글링으로 mockito, page, test, querydsl, parameter 등 다양하게 검색 해봤는데 원하는 결과를 얻기 못해 질문 한번 드려봅니다.

 

혹시나 제가 잘못된 방향으로 테스트를 진행하고 있는건지 혹은 다른 방법이 있을지 궁금합니다!

깃저장소도 같이 공유드립니다.

https://github.com/heechul90/heech-heechlog-server

 

 

답변 1

답변을 작성해보세요.

0

안녕하세요. 호돌맨입니다.

given(postQueryRepository.findPosts(condition, pageRequest)).willReturn(new PageImpl<>(posts));

위 코드에서 postQueryRepository.findPosts를 할 경우 posts(30개)를 반환하도록 설정 하셨기 3개가 나올 수 없습니다.

그치만.. 코드쨩.. 분명 PostSearchCondition으로 필터링 했는걸?

postQueryRepositorys는 Mock 상태입니다. Mock은 실제로 findPosts 코드를 실행하지 않습니다.
확인 해보시려면 PostQueryRepository.java안에 findPosts 첫 번째 라인에 breakpoint를 찍으신 뒤 debug 모드로 테스트를 실행하시면 breakpoint가 걸리지 않는 걸 확인해보실 수 있습니다.

QueryDSL 테스트시 @DataJpaTest검색 해보시는걸 추천드립니다.

감사합니다.