Kotlin
[Spring Boot 3.0 / Spring Security 6.0] Controller에서 시큐리티 인증 mocking 후 테스트 하기(401 피하기)
keep it simple
2024. 1. 11. 16:57
문제
- 스프링 부트 3.2 / Spring Security 6.0 적용을 한 후 유저가 모임을 생성하는 API를 테스트 해야된다. 하지만 애석하게도 인증 실패로 401이 반환된다.
주어진 상황
설정된 스프링 시큐리티
- 밑과 같이 http.authorizedHttpRequests 안에 permitAll()된 엔드포인트들만 인증을 안해도 접근이 가능한다. 이 외에 모든 엔드포인트에는 인증이 필요하다.
@Bean
fun securityFilterChain(
http: HttpSecurity,
jwtAuthenticationFilter: JwtAuthenticationFilter,
): DefaultSecurityFilterChain {
http
.csrf { it.disable() }
.headers { it.frameOptions { frame -> frame.disable() } }
.formLogin { it.disable() }
.httpBasic { it.disable() }
.authorizeHttpRequests {
it
.requestMatchers("/api/auth", "/swagger-ui/**", "/v3/api-docs/**", "/error")
.permitAll()
it
.anyRequest()
.authenticated()
}
.sessionManagement {
it.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
}
.authenticationProvider(authenticationProvider)
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter::class.java)
.exceptionHandling {
it.authenticationEntryPoint(customAuthenticationEntryPoint)
}
테스트코드
- 밑에 api/v1/gatherings는 인증이 필요한 엔드포인트다.
class CrewControllerTest : ControllerSupport() {
@MockBean
private lateinit var crewRepository: CrewRepository
@MockBean
private lateinit var crewService: CrewService
@Test
@DisplayName("모임을 등록한다.")
fun createCrew() {
// given
val createRequest = createCrewRequest()
// when
val apiStatus = performPost("/api/v1/gatherings", createRequest)
val successStatus = 200
// then
assertEquals(apiStatus, successStatus)
}
}
테스트 작동시 밑과 같은 테스트 실패가 나온다.
어떻게 해결할까?
- 인증만 모킹할 경우에는 스프링 시큐리티 테스트 패키지에서 제공하는 @WithMockUser 를 사용하면 된다.(밑에는 해당 어노테이션 내부 코드다.)
- 어노테이션 내부 코드를 보면 기본값으로 유저 value는 user이고 권한도 USER이다.
- 만약 특정 유저이름과 특정 유저 권한으로 테스트하고싶을 경우에는 밑과 같이 어노테이션안에 필드 값 채워준 후 테스트하면 된다.
@Test
@DisplayName("크루를 등록한다.")
@WithMockUser(username = "testUser", roles = ["ADMIN"])
fun createCrew() {
// given
val createRequest = createCrewRequest()
// when
val apiStatus = performPost("/api/v1/crews", createRequest)
val successStatus = 200
// then
assertEquals(apiStatus, successStatus)
}