본문 바로가기

STUDY/Spring

JUnit5 | @WebMvcTest와 @SpringBootTest

테스트 코드... 짜고싶어요 제발...

@WebMvcTest

  • @WebMvcTest는 Web Layer만 테스트할 때 사용
  • @WebMvcTest(ContollerClassName.class)로 특정 컨트롤러만 인스턴스화 하여 테스트하는 것도 가능
  • 실제 연결이 생성되는 것은 아님
  • 컨트롤러의 의존성은 @MockBean으로 모의 의존관계 생성 및 주입
  • MockMvc객체를 주입받아 해당 객체를 이용하여 테스트 진행

이렇게 테스트 클래스에 애노테이션을 붙여 사용한다.

@WebMvcTest
public class WebLayerTest {

}

아래와 같이 컨트롤러에 의존관계가 설정되어 있다면,

@RestContoller
public class HelloController {

    @Autowired
    private HelloService helloService;

}

@MockBean을 통해 테스트 클래스에서도 의존관계를 모의로 생성 및 주입할 수 있다.

@WebMvcTest(HelloController.class)
public class HelloControllerTest {

    @Autowired
    private MockMvc mockMvc;    // 컨트롤러 테스트를 위해 MockMvc 객체 의존관계 주입

    @MockBean
    private HelloService helloService;

}

 

테스트 메서드는 @Test애노테이션을 붙여 설정한다. 위에서 주입한 MockMvc를 통해 웹 레이어 테스트를 진행

테스트 메서드 이름은 한글로 적어도 무방하다

@Test
public void 조회_테스트() {
    this.mockMvc.perform(get("/books"))...
}

 


@SpringBootTest

  • @SpringBootTest를 사용하게 되면 웹 애플리케이션 컨텍스트에 대한 모든 구성이 로드
  • 애플리케이션의 모든 Bean을 스캔해 로드하기 때문에 실제 환경과 동일하게 테스트 할 수 있으나, 시간이 오래걸림
  • @ExtendWith를 명시할 필요 없음 (이미 포함되어 있기 때문)
  • 통합 테스트에서 사용되는 애노테이션
  • 단위 테스트에서 사용할 수는 있음 -> 속성 설정을 통해 구성 요소를 제한하여 테스트 하는 것이 좋음
  • @MockBean을 이용하면 실제 Bean 객체를 모의(Mock) 객체로 대신하여 사용할 수 있음
  • @Transactional 어노테이션을 명시하면, 테스트 메서드가 실행될 때 마다 롤백 처리 됨

 

기본적으로 @SpringBootTest는 서버를 시작하지는 않는다. webEnvironment설정을 통해 테스트를 어떤 환경에서 시작할 건지 설정한다.

  • MOCK (default) : 내장 서버가 실행되지않는다. @AutoConfigureMockMvc@AutoConfigureWebTestClient 애노테이션과 함께 mock 기반 테스트를 실행
  • RANDOM_PORT : 랜덤 포트 번호로 실제 웹 서버와 함께 WebServerApplicationContext가 로드된다.
  • DEFINE_PORT : 설정된 포트 번호로 실제 웹 서버와 함께 WebServerApplicationContext가 로드된다.
  • NONE : SpringApplication을 통해 ApplicationContext를 로드하지만 어떤 웹 환경도 제공하지 않음.

RANDOM_PORT나 DEFINE_PORT를 설정한 경우, 실제 서블릿 환경이 실행되기 때문에 별도의 트랜젝션에서 실행됨. 이 경우 트랜잭션은 롤백되지 않음

 

아래처럼 테스트 클래스에 @SpringBootTest애노테이션을 명시해 통합 테스트를 진행할 수 있다.
@LocalServerPort애노테이션은 실제 사용된 포트 번호를 주입해준다.

실제 웹 서버가 구동되기 때문에, RestTemplate을 통해 요청할 수 있는데, TestRestTemplate을 제공하기 때문에 이를 사용할 것을 권장한다.

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class MyControllerTest {

    @LocalServerPort
    private int port;    // 실행된 포트번호를 알 수 있다

    @Autowired
    private TestRestTemplate restTemplate;

    @Test
    public void 테스트_예시() {
        String body = this.restTemplate.getForObject("/b", String.class);
        assertThat(body).isEqualTo("Hello World");
    }

}

WebTestClient를 이용해 테스트하는 방법도 있다. 이는 WebFlux를 기반으로 작동한다.

 

 

실제 서버를 구동하지 않고, mock 기반 환경에서 테스트하려면 @AutoConfigureMockMvc 애노테이션을 함께 명시한다.
그리고 MockMvc를 이용해 요청한다.

오직 웹 레이어만 테스트하는 용도라면, @WebMvcTest를 이용하는 것이 훨씬 경제적이다.

@SpringBootTest
@AutoConfigureMockMvc
public class MyControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void 테스트_예시() {
        this.mockMvc.perform(get("/))
            .andExpect(status().isOk())
            .andExpect(content().string("Hello world"));
    }
}

 


 

46. Testing

A Spring Boot application is a Spring ApplicationContext, so nothing very special has to be done to test it beyond what you would normally do with a vanilla Spring context. By default, @SpringBootTest will not start a server. You can use the webEnvironment

docs.spring.io