@DataJpaTest의 동작 방식과 몇 가지 주의사항

kindof

·

2023. 2. 12. 22:36

1. @DataJpaTest

@DataJpaTest는 이름에서 알 수 있듯이 JPA Component의 테스트에 집중하기 위한 어노테이션입니다. 

@DataJpaTest

위 사진의 빨간색 박스로 표시한 내용을 자세히 읽어보면 크게 세 가지 특징이 있습니다.

 

첫째, @DataJpaTest는 Transactional하며 각 테스트의 마지막에 롤백을 합니다.

 

둘째, 기본적으로 in-memory DB를 사용하며, @AutoConfigureTestDatabase 어노테이션을 통해 사용자가 지정하는 DB로 설정할 수 있습니다.

 

셋째, Bean 스캔의 범위가 한정적입니다. 어플리케이션에서 등록한 모든 Bean을 대상으로 테스트를 하기 위해서는 @SpringBootTest를 사용해야 합니다.

 

각 내용에 대해 자세히 설명해보겠습니다.

 

2. Rollback

기본적으로 @Transactional + @Test 어노테이션은 각 테스트의 마지막에 예외 발생 여부와 관계없이 롤백을 진행합니다. 

 

그리고 @DataJpaTest는 @Transactional을 포함하므로 따로 @Transactional 어노테이션을 추가하지 않아도 각 테스트는 마지막에 롤백됩니다.

@Transactional 어노테이션이 포함되어 있다.

이를 증명하기 위해 아래와 같이 yml 파일에 Logging 레벨을 'DEBUG'로 지정하고, 테스트 코드를 실행해보겠습니다.

logging:
  level:
    org.springframework.orm.jpa: DEBUG
    org.springframework.transaction: DEBUG
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
class MemberRepositoryTest {

    @Autowired
    MemberRepository memberRepository;

    @Test
    public void memberSaveTest() {
        Member member = Member.builder().email("test@naver.com").nickname("sh").password("1234").build();
        memberRepository.save(member);

        Optional<Member> result = memberRepository.findByEmail("test@naver.com");
        boolean present = result.isPresent();
        Assertions.assertTrue(present);
    }
}

트랜잭션이 롤백된다.

빨간색 박스로 표시한 로그처럼 JPA 트랜잭션이 롤백됩니다.

 

@DataJpaTest를 사용하면서 롤백을 하지 않기 위해서는 @Rollback(false) 옵션을 사용합니다. 아래 테스트 코드를 실행해보겠습니다.

@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@Rollback(false)
class MemberRepositoryTest {

    @Autowired
    MemberRepository memberRepository;

    @Test
    public void memberSaveTest() {
         // 동일한 코드
    }
}

트랜잭션이 커밋된다.

트랜잭션이 롤백되지 않고 커밋된 채 종료됩니다.

 

 

3. Bean Scan

@DataJpaTest 어노테이션을 바탕으로 한 테스트에서는 @Entity를 통해 Bean으로 등록된 클래스만을 ApplicationContext에 로드합니다. 

 

따라서 아래와 같이 @DataJpaTest에서 @Service와 같은 어노테이션을 통해 Bean으로 등록된 클래스를 주입하려고 하면 아래와 같은 에러를 만나게 됩니다.

@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
class MemberRepositoryTest {

    @Autowired
    MemberService memberService;

    @Autowired
    MemberRepository memberRepository;

    @Test
    public void memberSaveTest() {
    
        // 테스트 로직 
        
    }
}

Error creating bean with name ...

따라서 Controller, Service 레이어에 대한 단위 테스트나 다른 통합 테스트를 하기 위해서는 @SpringBootTest를 사용해야 합니다.

 

 

4. @AutoConfigureTestDatabase

@DataJpaTest는 기본적으로 in-memory DB인 H2 DB를 사용합니다. 이는 @DataJpaTest가 기본적으로 JPA Repository 계층을 테스트하기 위한 목적에 방점을 두고 있기 때문인데요.

 

H2와 같은 DB를 사용하면 별도로 DB를 생성할 필요도 없고 앞서 말한 자동 롤백 기능으로 편리하게 데이터 간의 간섭없이 테스트를 할 수 있습니다.

 

따라서, 사용자가 직접 지정한 데이터베이스를 가지고 테스트를 하기 위해서는 아래와 같이

@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)

@AutoConfigureTestDatabase 어노테이션을 통해 자동으로 설정되는 H2 DB를 오버라이딩 해야 합니다.

 

만약 위와 같은 설정도 없고 H2 DB도 설정도 없다면, 아래 테스트를 실행했을 때 dataSource를 지정하라는 에러와 함께 @AutoConfigureTestDatabase 어노테이션을 추가하라는 가이드가 나옵니다.

@DataJpaTest
//@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
class MemberRepositoryTest {

    @Autowired
    MemberRepository memberRepository;

    @Test
    public void memberSaveTest() {
        
        // 테스트 코드
    }
}

Error creating bean with name 'dataSource'

 

4. Reference

https://docs.spring.io/spring-boot/docs/2.3.3.RELEASE/reference/htmlsingle/#boot-features-testing-spring-boot-applications-testing-autoconfigured-mvc-tests

 

Spring Boot Reference Documentation

This section goes into more detail about how you should use Spring Boot. It covers topics such as build systems, auto-configuration, and how to run your applications. We also cover some Spring Boot best practices. Although there is nothing particularly spe

docs.spring.io