SMALL
@WebMvcTest 어노테이션은 Controller Layer를 테스트할 때 사용된다.
( https://joomn11.tistory.com/86 )
해당 어노테이션을 사용하면 Spring MVC 컨트롤러를 이용한 요청과 응답에 필요한 Bean들만 로딩하여 가벼운 테스트 환경을 제공한다.
@WebMvcTest 어노테이션을 사용시 다음 내용만 스캔하도록 제한한다
@Controller,
@ControllerAdvice,
@JsonComponent,
Converter / GenericConverter,
Filter,
WebSecurityConfigurerAdapter,
WebMvcConfigurer,
HandlerMethodArgumentResolver
@Component, @Service or @Repository Bean들은 스캔에서 제외된다.
Spring Security에 대한 설정은 @WebMvcTest의 스캔 대상에 해당한다.
하지만, 대부분의 Spring Security에서는 다른 Bean들에 대한 Dependency가 존재하게 된다.
@RequiredArgsConstructor
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final CustomOAuth2UserService customOAuth2UserService; // Dependency!!
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().headers().frameOptions().disable()
.and().authorizeRequests()
.antMatchers("/", "/css/**", "/js/**", "h2-console/**").permitAll()
.antMatchers("/api/**").hasRole(Role.USER.name()).anyRequest().authenticated()
.and().logout().logoutSuccessUrl("/")
.and().oauth2Login()
.userInfoEndpoint()
.userService(customOAuth2UserService);
http.csrf().disable().headers().frameOptions()
.disable().and().authorizeRequests().anyRequest().permitAll();
}
}
그렇기 때문에 @WebMvcTest를 진행할 경우 아래와 같은 에러를 보게 된다.
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException:
Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type '${classInfo}' available: expected at least 1 bean which qualifies as autowire candidate.
해당 문제를 해결하기 위해서는 Controller Layer에 해당하는 내용에만 Test를 집중할 수 있도록 WebSecurityConfigurerAdapter를 스캔 대상에서 제외하고 @WithMockUser를 통해 Mock 인증 사용자를 생성한다.
@WebMvcTest(controllers = HelloController.class,
excludeFilters = { //!Added!
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = SecurityConfig.class) })
public class HelloControllerTest {
@Autowired
private MockMvc mvc;
@Test
@WithMockUser(roles = "USER") //!Added!
public void hello가_리턴된다() throws Exception {
String hello = "hello";
mvc.perform(get("/hello")).andExpect(status().isOk()).andExpect(content().string(hello));
}
}
LIST
'Spring > etc' 카테고리의 다른 글
[Spring] @PreAuthorize, @PostAuthorize에서 Custom Security Expression 사용하기 (0) | 2021.11.27 |
---|---|
[Spring] Spring Security Annotation (@PreAuthorize, @PostAuthorize, @Secure) (0) | 2021.11.24 |
[Spring] Controller Layer Test 코드 작성 (+예시) (0) | 2021.09.09 |
[Spring] Interceptor란 (+사용 예제) (0) | 2021.09.05 |
[Spring] 구동 시점 로직 추가 (CommandLineRunner ApplicationRunner) (0) | 2021.09.02 |