Test코드에 관하여 : @DataJpaTest와 @SpringBootTest 의 차이? (Feat. Spock+그루비)

박두팔이·2023년 5월 24일
0

처음 테스트코드를 Spock를 이용하여 작성하려고 할 땐, 왜 @Mock객체를 스프링부트가 인식할 수 없는지 알지 못했다.

⭐️ [이전블로그보기]Spock 테스트프레임워크를 사용할 때 @Mock import안되는 문제

간단히 요약하자면 JPA Repository 인터페이스는 스프링 데이터 JPA에 의해 동적으로 구현되기 때문에 단순히 @Mock 어노테이션으로는 모킹할 수 없다. 따라서 추가적인 작업이 필요했는데 그것은 @SpringBootTest 어노테이션을 사용하여 테스트 클래스에서 스프링 컨텍스트를 로드하고, @MockBean 어노테이션을 사용하여 JPA Repository 인터페이스를 모킹하는 방법이었다.

@SpringBootTest
class UserControllerSpec extends Specification {

    @Subject
    UserController userController

    @MockBean
    UserRepository userRepository
    ...
    ...
    ...
}

하지만 이럴경우 OverloadingMethod를 Mocking 해야할 때 동적언어인 Groovy 특성상 어떤 메소드를 Mocking해야할 지 선택하지 못해서 Mocking실패로 테스트가 실패하는 문제가 발생한다. (참고하자면, Junit기반으로 변경해서 코드를 작성하면 테스트가 성공한다.)

Spock 테스트 프레임워크가 지원하는 Spring Mock으로 OverloadingMethod를 Mocking을 할 수 있도록 위의 문제를 해결할 수 있는데 이 또한, JPA에서 제공하는 JpaRepository 인터페이스를 사용하고 있다면 Mocking하지 못한다. 즉, JPA의
JpaRepository 인터페이스는 JPA의 영속성 컨텍스트와 상호작용하기 때문에 목 객체로 직접 생성할 수 없다는 뜻이다.

JPA가 cglib 프록시를 생성하면서 Spock 프레임워크가 Mock으로 생성한 프록시를 무시하기 때문에 Mocking이 되지 않고 JPA가 구현체를 생성해버리니 테스트가 항상 실패하고 마는 것이다.

따라서 JPA Repository를 사용하면서 Overloadiong된 Method를 사용하려면 테스트 환경설정을 하는 방법이 있다. @DataJpaTest 애노테이션을 사용하여 인메모리 데이터베이스를 설정하는 방법이다.

@DataJpaTest
class UserControllerSpec extends Specification {

    @MockBean
    DefaultUserService defaultUserService

    UserController userController = new UserController(defaultUserService, /*mockReadOnlyUserService*/, /*mockCvService*/)

기존에 작성한 테스트 코드에서 @SpringBootTest 애너테이션을 지우고 @DataJpaTest을 사용한 코드로 수정하였다.


그렇다면 @DataJpaTest와 @SpringBootTest의 차이는 무엇일까?

@DataJpaTest

  • 주로 JPA 기반의 데이터 액세스 레이어를 테스트 할 때 사용된다.
  • 내부적으로 내장형 데이터베이스 (인메모리 데이터베이스)를 설정하고 JPA리포지토리 및 관련된 구성 요소를 자동으로 구성한다.
  • 실제 데이터베이스 연결이 필요하지 않고 테스트용 데이터베이스를 사용하여 테스트를 실행해야 한다.
  • 테스트 실행 시간을 단축시키고 테스트 간의 의존성을 격리하여 테스트의 신속성과 안정성을 높인다.

@SpringBootTest

  • 스프링 애플리케이션의 전체적인 컨텍스트를 로드하여 테스트할 때 사용된다.
  • 실제로 실행 가능한 애플리케이션과 동일한 설정을 사용하여 테스트를 실행한다.
  • 애플리케이션 컨텍스트의 로딩 및 초기화에 시간이 걸리기 때문에 테스트 실행 시간이 더 오래 걸릴 수 있다.
  • 실제 데이터베이스 연결이 필요하거나 외부 서비스와의 상호 작용을 테스트할 때 유용하다.
profile
기억을 위한 기록 :>

0개의 댓글