인프런 커뮤니티 질문&답변

구준형님의 프로필 이미지
구준형

작성한 질문수

Java/Spring 테스트를 추가하고 싶은 개발자들의 오답노트

페이징 기능은 어떻게 테스트 하시나요?

작성

·

522

·

수정됨

0

안녕하세요. 강사님 강의듣고나서 새로운 시각이 열리게 된 것 같아서 요새 개발을 재밌게 배우고 있습니다. 감사합니다.

배경

public interface PostJpaRepository extends JpaRepository<PostEntity, Long> {
    @Query(value = "select new store.ppingpong.board.post.dto.PostWithWriter(p.id, p.title, p.postType, u.userInfo.nickname, p.createdAt) " +
            "from PostEntity p " +
            "join UserEntity u on p.userId = u.id " +
            "where p.forumId = :forumId", countQuery = "select count(p) from PostEntity p where p.forumId = :forumId")
    Page<PostWithWriter> findPostAndUsernameByForumId(@Param("forumId") String forumId, Pageable pageable);
}

(Post는 User의 id를 필드로 가지고 있고 Forum을 조회 시, forumId와 같은 Post리스트를 페이징처리하면서, User의 name필드 정보가 필요해서 다음과 같은 쿼리를 작성한 상황입니다.)

페이징 기능이 필요해서, 제일 먼저 생각난게 spring data jpa에서 제공하는 페이징기능이었습니다.

그런데, 테스트코드를 작성하려보니 뭔가 잘못된 것 같다고 느꼈습니다.

문제상황

@Override
public Page<PostWithWriter> findByForumId(String forumId, Integer listNum, Pageable pageable) {
    List<Post> list = data.stream()
            .filter(post -> post.getForumId().equals(forumId))
            .toList();
    FakePage<Post> posts = new FakePage<>(list, pageable.getPageNumber(), pageable.getPageSize(), list.size());
    posts.stream()
            .map() // ???
    return null;
}

FakePostRepository를 작성하던 중 Page를 상속받은 FakePage를 구현 후, "스트림으로 PostWithWriter dto에 넣어줘야겠다" 라고 생각할 때였습니다.

위 상황에서는 Post를 받는 정적 팩토리 메서드를 만들면 될 것 같긴했습니다. 그러나, 테스트코드를 위해서 메인코드를 수정해야하는 상황이 좀 이상하다고 생각했습니다.

질문

일단 제가 이 상황에서 드는 다양한 생각은

  1. dto는 단순히 전달목적이니 코드수정이 들어가도 상관없다.

  2. jpa의 페이징기능을 포기하고 Comparator를 구현해서 직접 정렬한다.

  3. 페이징 기능에 한해서 Mock 프레임워크 기능을 이용한다.

     

물론 지금은 서비스가 단순히 repository를 호출하는거라 테스트 할 의미가 적은 것 같지만, 나중에 위 같은 상황에서의 대처가 궁금해서 질문올립니다.

강사님의 답변을 듣고 싶습니다. 감사합니다!

답변 1

-2

안녕하세요, 인프런 AI 인턴입니다.

구준형님의 질문에 대해 답변 드리겠습니다.

일반적으로 Spring Data JPA와 같은 ORM을 사용할 때, 페이징 처리는 Pageable 인터페이스를 통해 쉽게 구현할 수 있습니다. 또한 페이징 기능과 관련된 테스트 코드를 작성하는 경우에도 PageableSort를 활용할 수 있습니다.

페이징 기능을 테스트하는 방법 중 하나는 실제 DB 대신 H2와 같은 인메모리 데이터베이스를 사용하는 것입니다. 이를 통해 페이징 기능을 직접 실행해보고 결과를 검증할 수 있습니다. 그리고 페이징 처리된 결과를 검증하는 것은 Page 인터페이스가 제공하는 다양한 메서드(getContent(), getTotalElements(), getTotalPages() 등)를 활용하여 구현할 수 있습니다.

그러나 실제 Service 계층이나 Controller 계층에서의 페이징 기능 테스트를 위해서는 Mock 프레임워크를 사용하는 것이 좋습니다. Spring에서 제공하는 @WebMvcTest 등의 어노테이션과 함께 Mockito와 같은 Mock 프레임워크를 사용하여 페이징 처리가 포함된 메서드를 테스트 할 수 있습니다.

구준형님이 제시한 방안 중 3번째 방안인 “페이징 기능에 한해서 Mock 프레임워크 기능을 이용한다.“가 가장 적절해 보입니다. 이 방법을 통해 실제 데이터베이스에 의존하지 않고도 원하는 페이징 처리 로직을 검증할 수 있습니다. 또한, 테스트 환경 구성이 복잡해질 수 있는 단점도 해결할 수 있습니다.

Spring Boot에서는 MockMvc를 사용하여 웹 계층의 테스트를 쉽게 구현할 수 있습니다. @WebMvcTest 어노테이션과 함께 사용하면 자동으로 필요한 설정들을 로드하여 테스트 환경을 구성할 수 있습니다.

source

따라서 페이징 기능을 포함한 비즈니스 로직의 테스트를 위해 Mock 프레임워크를 적극 활용하는 것을 권장드립니다. Mock 객체를 사용하여 페이징 결과를 가정하고 해당 결과에 대한 처리가 올바르게 이루어지는지 검증하는 방식으로 테스트를 진행해보시길 바랍니다.

질문에 충분한 답변이 되었기를 바랍니다. 추가적인 질문이 있다면 언제든지 질문해주세요. 감사합니다!

구준형님의 프로필 이미지
구준형

작성한 질문수

질문하기