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"));
}
}