@WebMvcTest를 사용하면 Controller만 단위 테스트가 가능하다. @SpringBootTest를 사용하면 통합테스트가 되기 때문에 Controller만 단위 테스트를 하기 위해서는 @WebMvcTest를 이용하면 된다.
@SpringBootTest를 사용해도 테스트에 문제는 없지만 통합테스트가 목적이 아닌 단위테스트가 목적이기 때문에 목적에 맞게 @WebMvcTest를 사용하는 것을 추천한다. 이 글은 @WebMvcTest를 이용한 테스트 과정 중 첫번째로 맞히한 에러 상황과 해결 방법에 대해 정리한 글이다.
@WebMvcTest를 이용한 REST API 테스트 중 맞이한 에러 해결기 (1)
에러 상황
@WebMvcTest를 이용하여 테스트 코드를 작성 중 다음과 같은 오류를 맞이했다.
NoSuchBeanDefinitionException이 발생된 원인은 바로 @WebMvcTest 특성 때문이다.
@WebMvcTest 는 @Controller, @RestController가 설정된 클래스들을 찾아 메모리에 생성한다. @Service나 @Repository가 붙은 객체들은 테스트 대상이 아닌 것으로 처리되기 때문에 생성이 되지 않는다.
그리고 추가적으로 Controller와 관련된 빈을 자동으로 Configuration 하는데 해당 빈들은 다음과 같다.
- @ControllerAdvice
- @JsonComponent
- Converter
- GenericConverter
- Filter
- WebMvcConfigurer
- WebSecurityConfigurerAdapter
- HandlerMethodArgumentResolver
그런데 이때 WebSecurityConfig 클래스에서 사용할 서비스를 주입받고 있는데 해당 서비스는 @Service로 선언되어 있으니 해당 서비스가 빈 생성이 되지 않아 일어나는 문제였다.
내부적으로 사용하는 WebSecurityConfig 클래스는 WebSecurityConfigurerAdapter()를 상속받고 있기 때문에 빈으로 등록되게 되는 것이다.
해결방법
해결을 하기위해서는 @WebMvcTest에 excludeFilters에 WebSecurityConfig를 선언해서 제외를 시켜주면 된다. 즉, WebSecurityConfig Class를 스캔되지 않도록 하는 것이다.
방법은 아래와 같다.
@WebMvcTest(excludeFilters = [ComponentScan.Filter(value = [(WebSecurityConfig::class), /*추가로 선언 가능*/])
만약 문제가 되는 class들이 많다면 Filter에 value 값은 배열이기 때문에 추가적으로 선언을 하면 된다.
다음 시간에는 해당 에러를 잡고나서 터진 JPA metamodel must be empty! 에 대해서 정리한다.
댓글