waveofmymind
기록하는 습관
waveofmymind
전체 방문자
오늘
어제
  • 분류 전체보기 (124)
    • 📝 정리 (5)
    • 🌊TIL (9)
    • 💻CS (1)
      • 자료구조 (1)
    • 📙Language (9)
      • ☕Java (6)
      • 🤖Kotlin (3)
    • 🍃Spring (28)
    • 👨🏻‍💻알고리즘 (67)
      • 프로그래머스 (59)
      • 백준 (3)
    • 👷DevOps (4)
      • 🐳Docker (2)
      • 🤵Jenkins (1)

블로그 메뉴

  • 홈
  • Spring
  • Java
  • 알고리즘

공지사항

인기 글

태그

  • Connection
  • Spring Security
  • 스택
  • 트랜잭션 전파
  • spring boot
  • LeetCode
  • resultset
  • 다이나믹 프로그래밍
  • 통합테스트
  • JDBC
  • SpringAOP
  • 스프링 시큐리티
  • BFS
  • CORS
  • 스프링
  • AOP
  • 챗GPT
  • kotest
  • 코틀린
  • chat GPT
  • Open AI
  • mybatis
  • 스프링 부트
  • 완전탐색
  • 트랜잭션
  • kotlin
  • 힙
  • til
  • sql
  • spring

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
waveofmymind

기록하는 습관

[Spring] WebMvcTest에서 발생하는 SpringSecurity 의존성 문제 해결하기
🍃Spring

[Spring] WebMvcTest에서 발생하는 SpringSecurity 의존성 문제 해결하기

2023. 4. 19. 11:42

AS-IS

UserController의 테스트를 해보기 위해

@ExtendWith(SpringExtension.class)
@WebMvcTest(controllers = UserController.class,

를 사용해서 테스트 코드를 작성하던 중, 다음과 같은 예외가 발생했다.

Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name '~~' defined in file [~~]: Unsatisfied dependency expressed through constructor parameter 1; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type '~~' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}

이는, WebMvcTest가 MVC에 초점을 맞춰서 스프링 빈으로 가져오기 때문에, @Service, @Controller, @Component 등이 해당된다.

이 때, Spring Security 관련 구성도 가져오기 때문에,

나의 경우는 Security Config에서 사용하는 JwtAuthorizationFilter, 그리고 다시 필터에서 사용하는 JwtVerifier에 대해 예외가 발생했다.

 

즉, Security 관련 컴포넌트에서 의존하는 빈들이 @WebMvcTest에 걸리지 않으면 발생하는 예외인 것이다.

해결 과정

나는 Spring Security를 테스트 하는 것이 아닌 UserController에 대해 테스트 하는 것이기 때문에, @WebMvcTest에 걸리는 SecurityConfig와, 관련 JwtVerifier, JwtAuthorizationFilter도 제외시켰다.

@ExtendWith(SpringExtension.class)
@WebMvcTest(controllers = UserController.class,
excludeFilters = {
        @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = SecurityConfig.class),
        @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = JwtAuthorizationFilter.class),
        @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = JwtVerifier.class)
})
public class UserControllerTest {...}

그리고, 다시 결과를 확인해보니

 

401 에러가 발생했다. 

이는 Securirty의 인증 필터에 의해 인증이 되지 않기 때문에 발생하는 권한이 없다는 예외이다.

 

그러므로 @WithMockUser를 이용해서 인증을 시도해야한다.

@DisplayName("로그인 API 테스트")
@Test
@WithMockUser
void givenRequest_whenLogin_then200() throws Exception {...}
@WithMockUser vs @WithMockAuthUser
@WithMockUser: 테스트 시 지정된 사용자 세부 정보(사용자 이름, 비밀번호, 권한 등)로 인증된 사용자를 시뮬레이션할 수 있다. 예를 들어, 특정 사용자 이름과 권한을 가진 사용자가 인증된 것처럼 시뮬레이션하기 위해 사용한다.
@WithMockAuthUser: 애플리케이션에 특화된 사용자 세부 정보를 인증 객체에 삽입하는 데 사용한다. 그러나 이를 사용하기위해서는 WithSecurityContextFactory와 같은 사용자 세부 정보를 제공하는 클래스를 구현해야한다.
정리하면, 후자는 설정이 필요하지만 전자보다 애플리케이션에 특화된 사용자 정보를 이용해서 시뮬레이션 테스트를 할 수 있다.

 

결과 테스트가 정상적으로 실행되었다.

 

정리

  • @WebMvcTest를 할 때, Spring Security의 설정 정보도 빈으로 가져오기 때문에 JwtAuthorizationFilter와 같이 SecurityConfig에서 의존하는 빈들이 없기 때문에 UnsatisfiedDependencyException이 발생한다.
  • 개인적으로, 시큐리티의 필터는 컨트롤러 테스트가 아닌 직접 Postman을 통해 요청을 할 때 정상적으로 동작하는지 알 수 있기 때문에 컨트롤러 테스트에만 초점을 맞춰야한다고 생각했다.
  • 그래서 Security 관련 설정을 스캔하지 않도록 @WebMvcTest의 excludeFilter에 Security 관련 설정을 추가해서 스캔 대상에서 제외했다.
  • 단점으로 만약 Role을 여러개 다루고 있을 경우, Role마다 접근 가능한 경로가 달라질 수 있는데, 이에 대한 테스트가 불가능해진다는 단점이 있을 수 있겠다는 생각이 들었다.

 

 

 

'🍃Spring' 카테고리의 다른 글

[Spring] 스프링 빈 (1/2)  (0) 2023.05.26
[Spring] 테스트 클렌징시 deleteAll()을 사용할 때의 주의점  (0) 2023.05.13
[Redis] Redis 캐시를 사용한 JWT 리프레시 토큰 관리하기  (0) 2023.04.10
[Spring Security] CORS 문제 해결하기  (0) 2023.04.01
[Spring] 조회수 필드에 대해 동시성 문제 해결하기  (1) 2023.03.29
    '🍃Spring' 카테고리의 다른 글
    • [Spring] 스프링 빈 (1/2)
    • [Spring] 테스트 클렌징시 deleteAll()을 사용할 때의 주의점
    • [Redis] Redis 캐시를 사용한 JWT 리프레시 토큰 관리하기
    • [Spring Security] CORS 문제 해결하기
    waveofmymind
    waveofmymind

    티스토리툴바