TDD한걸음

[TDD한걸음] 1편 Springboot TestAnotation정리

닥치고개돌 2024. 2. 20. 19:52
728x90

TDD 들어가기 전에 기본적으로 테스트 코드를 작성하기 위한 문법을 알아야 TDD도 가능하다.
먼저 테스트 코드 작성을 돕는 어노테이션들을 알아보자!

Spring Boot는 기본적으로 웬만한 테스트 라이브러리들을 한데 뭉쳐놓은 테스트 스타터를 제공한다. (spring-boot-starter-test)

먼저 기본적으로 자주 사용되는 어노테이션들을 살펴보자

 

  • @SpringBootTest
  • @WebMvcTest
  • @DataJpaTest
  • @RestClientTest
  • @JsonTest

 

@SpringBootTest

 

@SpringBootTest통합 테스트를 제공하는 기본적인 스프링부트 테스트 어노테이션이다.
애플리케이션이 실행될 때의 설정을 임의로 바꾸어 테스트를 진행할 수 있으며 여러 단위 테스트를 하나의 통합된 테스트로 수행할 때 적합하다. Spring Boot 프로젝트를 만들면 메인 클레스와 함께 기본으로 제공된다.
@SpringBootTest는 만능이라 할 수 있는데, 실제 구동되는 애플리케이션과 똑같이 ApplicationContext를 로드하여 테스트하기 때문에 하고 싶은 테스트를 모두 수행할 수 있다.

단, 애플리케이션에 설정된 빈을 모두 로드하기 때문에 애플리케이션의 규모가 클수록 느려진다.

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBootTestApplicationTests {

    @Test
    public void contextLoads() {
    }
}

이 클래스를 실행하면 애플리케이션 컨텍스트를 로드하여 스프링 부트 테스트를 진행한다.

 

@RunWith 어노테이션을 사용하면 JUnit에 내장된 러너를 사용하는 대신 어노테이션에 정의된 러너 클래스를 사용한다. @SpringBootTest 어노테이션을 사용하려면 JUnit 실행에 필요한 SpringJUnit4ClassRunner 클래스를 상속받은 @RunWith(SpringRunner.class)를 꼭 붙여서 사용해야 한다. 그렇지 않으면 정상적으로 동작하지 않는다.

JUnit5부터는 @ExtendWIth(SpringExtension.class) 이렇게 사용!

  • @ActiveProfiles("test") : 프로파일 환경(개발, QA, 운영 환경)마다 다른 데이터소스(DataSource)를 갖는다면, @ActiveProfiles("test")과 같은 방식으로 원하는 프로파일 환경값을 부여
  • @Transactional 을 사용하면 테스트를 마치고 나서 수정된 데이터가 롤백된다.
  • @SpringBootTest는 기본적으로 검색 알고리즘을 사용하여 @SpringBootApplication이나 @SpringBootConfiguration 어노테이션을 찾는다. 스프링 부트 테스트이기 때문에 해당 어노테이션 중 하나는 필수

 

@DataJpaTest

 

@DataJpaTest 어노테이션은 JPA 관련 테스트 설정만 로드한다.
데이터소스의 설정이 정상적인지, JPA를 사용하여 데이터를 제대로 생성, 수정, 삭제하는지 등의 테스트가 가능하다. 또한 내장형 DB를 사용하여 실제 데이터베이스를 사용하지 않고 테스트 데이터베이스로 테스트할 수 있다.

@DataJpaTest는 기본적으로 인메모리 임베디드 데이터베이스를 사용하며, @Entity 클래스를 스캔하여 스프링 데이터 JPA 저장소를 구성한다. 만약, 최적화한 별도의 데이터소스를 사용하여 테스트하고 싶다면 기본 설정된 데이터소스를 사용하지 않도록 다음과 같이 설정한다.

@RunWith(SpringRunner.class)
@DataJpaTest
@ActiveProfiles("...") // ← 여기에 주목
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
public class JpaTest {
    // ...
}

@AutoConfigureTestDatabase 어노테이션의 기본 설정값인 Replace.Any를 사용하면 기본적으로 내장된 데이터소스를 사용한다. 위와 같이 Replace.NONE으로 설정하면 @ActiveProfiles에 설정한 프로파일 환경값에 따라 데이터소스가 적용된다.

이 외에도 자동 설정 방식을 이용해 설정할 수도 있다. application.yml에서 프로퍼티 설정을 spring.test.database.replace: NONE으로 변경하면 된다.

@DataJpaTestJPA 테스트가 끝날 때마다 자동으로 테스트에 사용한 데이터를 롤백한다. 또한 어떤 테스트 데이터베이스를 사용할 것인지도 선택할 수 있다. spring.test.database.connection: H2와 같이 프로퍼티를 설정하는 방법과, @AutoConfigureTestDatabase(connection = H2) 어노테이션으로 설정하는 방법이 있다. connection의 옵션으로 H2, Derby, HSQL 등의 테스트 데이터베이스 종류를 선택할 수 있다.

또한 @DataJpaTest에서 EntityManager의 대체제로 만들어진 테스트용 TestEntityManager를 사용하면 persist, flush, find 등과 같은 기본적인 JPA 테스트를 할 수 있다.

@RunWith(SpringRunner.class)
@DataJpaTest
public class BoardJpaTest {

    @Autowired
    private TestEntityManager boardTestEntityManager;

    @Autowired
    private BoardRepository boardRepository;

    @Test
    void Board_save_and_delete_test() {
        Board board1 = Board.builder()
                        .title("제목")
                        .createdAt(LocalDateTime.now()).build();
        boardTestEntityManager.persist(board1);

        Board board2 = Board.builder()
                        .title("제목2")
                        .createdAt(LocalDateTime.now()).build();
        boardTestEntityManager.persist(board2);

        boardRepository.deleteAll();
        assertThat(boardRepository.findAll(), IsEmptyCollection.empty());
    }
}

위 예제처럼 boardRepository의 deleteAll을 테스트하고싶을경우 save에 의존하지않고 저장된 Board객체가 두개 다 삭제 됐는지 테스트할 수 있다.

 

@RestClientTest

 

@RestClientTest는 REST 관련 테스트를 도와주는 어노테이션이다. REST 통신의 데이터형으로 사용되는 JSON 형식이 예상대로 응답을 반환하는지 등을 테스트할 수 있다.

 

@JsonTest

 

@JsonTest는 JSON 테스트를 지원하는 어노테이션이다. JSON의 직렬화와 역직렬화를 수행하는 라이브러리인 Gson과 Jackson API의 테스트를 제공한다. 각각 GsonTesterJacksonTester를 사용하여 테스트를 수행한다.

JSON 테스트는 크게 두 가지로 나뉜다. 문자열로 나열된 JSON 데이터를 객체로 변환하여 변환된 객체값을 테스트하거나 그 반대의 경우이다.

 

@RunWith vs @ExtendWith

 

해당 어노테이션들은 JUnit Test를 Spring TestContext Framework와 결합하는 것이다. JUnit 버전에 따라 다음과 같이 사용해야 한다.

// JUnit4
@RunWith(SpringRunner.class)

// JUnit5
@ExtendWIth(SpringExtension.class)

 

추가조사

 

@ContextConfiguration

@EnableAutoConfiguration

@AutoConfigureRestDocs

@AutoConfigureMockMvc

 

@Mock

@Spy

@MockBean

@Bean

@InjectMocks
@Autowired

@Nested

@Captor

@BeforeEach

@AfterEach

@ParameterizedTest

@ValueSource

@TestConfiguration

 

 

728x90

'TDD한걸음' 카테고리의 다른 글

[TDD한걸음] 2편 따라하면 바로 완성되는 TDD  (0) 2024.03.26