본문 바로가기

개발/Spring

WebMvcTest에서 Filter 제외하기

 

Spring boot 프로젝트에서 통합 테스트가 아닌 단위 테스트로 Api를 테스트 하는데 Filter 때문에 오류가 발생했다. api를 호출하면 무조건 filter를 거치는데 스캔은 Contoller만 하니까 처음에는 bean 생성 에러가 발생했고 어찌저찌 filter 제외 설정을 했더니 security 관련 에러가 발생했다. 그래서 filter를 제외하고, 가짜 사용자로 테스트를 하도록 했다.

 

실패한 테스트

@WebMvcTest(ReplyApiController.class)
class ReplyApiControllerTest {
    @Autowired
    private MockMvc mockMvc;

    @MockBean
    ReplyService replyService;

    @Test
    void testGetReplies() throws Exception {
        Long postId = 1L;
        
        ...

        given(replyService.findReplyByPostId(postId, pageable))
                .willReturn(response);

        mockMvc.perform(
                get("/reply/" + postId))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.replies").exists())
                .andDo(print());

        verify(replyService).findReplyByPostId(postId, pageable);

    }
}

 

에러 1

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

 

 

처음에는 jwt 설정 때문에 에러가 발생하는줄 알고 yml 파일을 import 했었다. 아무 변화가 없었고 TokenService를 Import 해서 다시 실행했다. 

@Import(TokenService.class)

 

에러 2

No qualifying bean of type 'security.jwt.TokenProvider' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}

 

 

이제는 다시 Service 안에 있는 의존성에서 에러가 발생, 그래서 계속 추가해줬더니 끝도 없이 의존성에 관한 에러가 발생하면서 결국 repository는 interface라서 추가가 안됐다. interface를 구현한 클래스로 import를 해주라고 하는데 JpaRepository를 구현할 수 없으니 다른 방법을 찾아봐야지

 

 

그래서 찾은 것이 특정 filter를 제외하는 설정이다.

@WebMvcTest(controllers = ReplyApiController.class, excludeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = TokenFilter.class))

- filter를 제외하는 설정인 줄 알았는데 필터링 설정이다. 그래서 다른 클래스도 제외할 수 있다.

- FilterType.ASSIGNABLE_TYPE: 특정 타입의 클래스 제외

- FilterType.ANNOTATION: 특정 어노테이션을 가진 클래스 제외

- FilterType.REGEX: 정규식을 통해 제외할 클래스의 이름 지정

 

 

이렇게만 작성했더니 테스트하는 api는 로그인이 필요없음에도 security 설정으로 인해 login 페이지로 redirect 되어 테스트가 실패했다.

 

일단 지금은 security를 포함한 통합 테스트가 목적이 아니기 때문에 security 없이 할 수 있는 방법을 찾아보았다.

 

가짜 사용자 이용

@Test
@WithMockUser

- 이 어노테이션은 메서드에 추가

- 가짜 사용자를 생성하여 실제 인증 없이 테스트를 할 수 있다.

- username, roles, password 등을 설정하여 사용자의 정보와 권한을 정의할 수 있다.

 

 

성공!

@WebMvcTest(controllers = ReplyApiController.class, 
    excludeFilters = @ComponentScan.Filter(
    type = FilterType.ASSIGNABLE_TYPE, classes = TokenFilter.class))
class ReplyApiControllerTest {

    ...
    
    @Test
    @WithMockUser
    void testGetReplies() throws Exception {
    
    ...
    
    }