@WebMvcTest 는 무엇일까?
공식문서에서는 이렇게 설명한다.
Annotation that can be used for a Spring MVC test that focuses only on Spring MVC components.
즉, 스프링 MVC 구성 요소에만 초점을 맞춘 스프링 MVC 테스트에 사용할 수 있는 어노테이션이다.
그리고
Using this annotation will disable full auto-configuration and instead apply only configuration relevant to MVC tests (i.e. @Controller, @ControllerAdvice, @JsonComponent, Converter/GenericConverter, Filter, WebMvcConfigurer and HandlerMethodArgumentResolver beans but not @Component, @Service or @Repository beans).
이런 설명도 나와있는데,
스프링부트의 auto-configuration 이 비활성되고 MVC 테스트와 관련된 구성만 적용된다고 한다. 괄호안에 있는 요소들만 스프링 컨테이너에 올라가게 된다.
그럼 @WebMvcTest 는 어떻게 생겼길래, 공식문서에서 말했듯 괄호안 요소들이 자동으로 등록되는지 메타 어노테이션인 @WebMvcTest 의 내부는 어떻게 생겼는지 알아보도록 하자
@TypeExcludeFilters(WebMvcTypeExcludeFilter.class)
@WebMvcTest 는 @TypeExcludeFilters(WebMvcTypeExcludeFilter.class) 이런 어노테이션이 적용되어 있다.
여기서 @TypeExcludeFilters 가 보이는데 이 어노테이션의 역할은,
@SpringBootApplication 구성 요소 검사에 적용해야 하는 TypeExcludeFilter 클래스 집합을 정의하기 위한 테스트에 사용할 수 있는 어노테이션이다.
즉 빈등록을 위한 TypeExcludeFilter 를 통해 등록할 빈의 집합을 WebMvcTypeExcludeFilter.class 명시해주는데
WebMvcTypeExcludeFilter.class 도 알아보자
WebMvcTypeExcludeFilter
이 클래스에서 드디어 글 제목에 관한 내용을 알 수 있는 부분을 찾았다.
public final class WebMvcTypeExcludeFilter extends StandardAnnotationCustomizableTypeExcludeFilter<WebMvcTest> {
private static final Class<?>[] NO_CONTROLLERS = {};
private static final String[] OPTIONAL_INCLUDES = { "com.fasterxml.jackson.databind.Module",
"org.springframework.security.config.annotation.web.WebSecurityConfigurer",
"org.springframework.security.web.SecurityFilterChain", "org.thymeleaf.dialect.IDialect" };
private static final Set<Class<?>> DEFAULT_INCLUDES;
static {
Set<Class<?>> includes = new LinkedHashSet<>();
includes.add(ControllerAdvice.class);
includes.add(JsonComponent.class);
includes.add(WebMvcConfigurer.class);
includes.add(WebMvcRegistrations.class);
includes.add(javax.servlet.Filter.class);
includes.add(FilterRegistrationBean.class);
includes.add(DelegatingFilterProxyRegistrationBean.class);
includes.add(HandlerMethodArgumentResolver.class);
includes.add(HttpMessageConverter.class);
includes.add(ErrorAttributes.class);
includes.add(Converter.class);
includes.add(GenericConverter.class);
includes.add(HandlerInterceptor.class);
for (String optionalInclude : OPTIONAL_INCLUDES) {
try {
includes.add(ClassUtils.forName(optionalInclude, null));
}
catch (Exception ex) {
// Ignore
}
}
DEFAULT_INCLUDES = Collections.unmodifiableSet(includes);
}
private static final Set<Class<?>> DEFAULT_INCLUDES_AND_CONTROLLER;
static {
Set<Class<?>> includes = new LinkedHashSet<>(DEFAULT_INCLUDES);
includes.add(Controller.class);
DEFAULT_INCLUDES_AND_CONTROLLER = Collections.unmodifiableSet(includes);
}
private final Class<?>[] controllers;
WebMvcTypeExcludeFilter(Class<?> testClass) {
super(testClass);
this.controllers = getAnnotation().getValue("controllers", Class[].class).orElse(NO_CONTROLLERS);
}
@Override
protected Set<Class<?>> getDefaultIncludes() {
if (ObjectUtils.isEmpty(this.controllers)) {
return DEFAULT_INCLUDES_AND_CONTROLLER;
}
return DEFAULT_INCLUDES;
}
@Override
protected Set<Class<?>> getComponentIncludes() {
return new LinkedHashSet<>(Arrays.asList(this.controllers));
}
}
DEFAULT_INCLUDES 상수를 확인해 보면,
이 클래스가 생성되는 순간 처음 @WebMvcTest 공식문서에서 보았던 요소들을 넣어주는 코드를 볼 수 있다.
그리고 DEFAULT_INCLUDES_AND_CONTROLLER 상수도 마찬가지로,
이 상수 바로 밑 코드를 보면 생성되는 순간 Contoller.class 를 넣어주는 것을 확인할 수 있었다.
결론
@WebMvcTest 는 Mvc 테스트를 할 때 아주 용이하다.
내 생각으론 스프링 컨터이너에 모든 빈을 등록하지 않아도 되어 조금 더 빨리 실행될 것 같다.
@TypeExcludeFilters(WebMvcTypeExcludeFilter.class) 이 Controller 관련 빈들만 등록한다.
'spring' 카테고리의 다른 글
ResponseEntityExceptionHandler 란? (2) | 2023.04.29 |
---|---|
spring boot - oracle wallet (0) | 2022.04.10 |
Gradle (0) | 2022.02.14 |
Maven 과 Gradle (0) | 2022.02.14 |