ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Spring Security를 적용한 Web Layer 테스트하기
    spring/test 2021. 2. 11. 12:50

    클라이언트로부터 http요청을 받아 서비스계층으로 요청을 위임하는 Controller는 단위테스트가 불가능하다고 생각했다.애초에 복잡한 비지니스로직보다는 http요청을 잘 전달받고 서비스계층에게 역할을 위임한 후 올바른 데이터가 올 것이란 믿음과 함께 request를 잘 리턴하기만 하면 됐기 때문이다.

     

    테스트를 하더라도 @SpringBootTest와 postman을 이용한 테스트를 했었고, 이는 결국 실제 애플리케이션을 띄우는 작업과 다를 바 없는 무의미한 테스트로 생각했다. 결국 테스트코드를 이용한 자동화 테스트보다는 서버를 띄운 수동테스트를 주로 했었다.

     

    그러던 중, @WebMvcTest에 대한 예제를 확인했고, @SpringBootTest보다 훨씬 가벼운 준?통합 테스트를 확인했다.(자동화가 가능한 큰 장점) 바로 적용해보았다.

     

    기본 예제만 바로 적용한 형태였고, 이 테스트가 정상 동작하면 다른 메서드나 로직에 대해서도 확장이 가능해 보였다.

     

    결과는 실패였고, 원인은 MemberController에서 주입받을 MemberService가 없다는 내용이었다. 그래서 @MockBean이라는 어노테이션을 통해 필요한 의존성만 지정할 수 있다는 걸 알았다.

    다시 테스트를 돌려보면

     

    이번에는 AuthenticationProvider가 주입되지 못한다는 오류를 뱉었다. 분명 이 객체는 시큐리티 설정에 주입해줬던 객체인데 도대체 WebMvcTest의 스캔범위가 어디까지인지 감이 안왔다. 결국, 돌려막기식 오류처리가 아닌 @WebMvcTest에 대해 알고 사용하기로 결심했다.

     

    공식 문서에 나온 대로 @WebMvcTest의 스캔 대상은 @Controller, @ControllerAdvice, WebMvcConfigurer 등등이 있었다. 그 중 시큐리티 적용을 위해 붙인 @EnableWebSecurity가 WebMvcConfigurer를 import하고 있는 걸 알 수 있다.즉, 시큐리티 설정 또한 @WebMvcTest의 스캔 대상이라는 것이고

    위 3개의 객체를 생성자를 통해 주입해줘야 하는데 스캔 대상에 포함되지 못한 세 객체는

    빈으로 등록되어 적절한 타이밍에 주입되지 못해서 에러가 발생한 것이다.

    마찬가지로 임시로 목빈을 만들어 테스트를 진행했다.

     

    ^^

    ?

     

    뜬금없이 JPA의 메타모델은 empty가 되면 안된다는 내용인데 해결이 이해가 힘들었다.

     

    구글링 결과

    stackoverflow.com/questions/51467132/spring-webmvctest-with-enablejpa-annotation

     

    Spring @WebMvcTest with @EnableJpa* annotation

    I have the following Main Class. @EnableJpaAuditing @SpringBootApplication @EnableJpaRepositories(repositoryFactoryBeanClass = EnversRevisionRepositoryFactoryBean.class) public class SampleApplica...

    stackoverflow.com

    @EnableJpaAudting이 문제였고 이 설정을 따로 config패키지의 클래스로 빼줬다.

    이후 다시 테스트를 돌려보면

    회원가입 요청 시 파라미터를 넣지 않았기 때문에 ControllerAdvice에서 에러를 핸들링해 400 오류 코드를 포함한 요청을 보낸 테스트가 성공했음을 확인했다. 이제 web계층과 직접적으로 연결된 controller도 준통합테스트를 진행해서 보다 가벼운 테스트를 할 수 있게 됐다 ^^

    댓글

Designed by Tistory.