이전 장을 끝으로 Spring Security가 프로젝트에 추가 되었다.
추가 된 내용이 시스템 전체에 주는 영향이 있는지 기존의 테스트코드 통해서 전체적으로 수행 검증할 필요가 생겼다.
역시 곱게 잘 될리가 없었다.
책에서는 모든 테스트코드가 에러가 발생하고 있었지만
나같은 경우는 HelloResponseDtoTest는 정상적으로 테스트가 진행되었다.
우선 눈에 띄는 에러를 먼저 살펴 보자.
expected: 200 OK
but was : 302 FOUND
200의 HttpStatus를 기대했으나 302가 리턴되었다.
이는 스프링 시큐리티의 인증관련 문제라고 책에서는 언급하고 있다.
스프링 시큐리티환경에서 테스트를 위한 도구를 추가해야 한다.
bundle.gradle에 spring-security-test 의존성을 추가하자.
이제 테스트 메소드에 롤을 부여해야 한다.
이때 사용하는 어노테이션이 @WithMockUser(roles = "USER") 인데,
이말은 MockMvc를 사용해야 한다는 의미이기도 하다.
PostsApiControllerTest 클래스에 MockMvc를 사용할 수 있도록 코드를 추가하자.
이제 테스트 메소드 별로 롤을 부여하고
MockMvc를 통해서 HttpStatus를 받아오도록 코드를 개선하자.
위의 설정만으로는 충분하지 않은것일까. 전혀 개선이 되지 않았다.
에러내용을 살펴보자.
Error creating bean with name 'springSecurityFilterChain' defined in class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.servlet.Filter]: Factory method 'springSecurityFilterChain' threw exception; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.security.oauth2.client.registration.ClientRegistrationRepository' available
원인을 구글링해보았으나 만족스러운 내용을 찾지 못했다.
책을 찬찬히 읽어보자.
답은 테스트코드에서 실행 할때 바라보는 application.properties에 관련 문제였다.
Junit을 이용할 때 기본적으로 별도의 properties를 따로 생성해주지 않으면
src/main/resources/application.properties 를 바라보도록 되어 있다.
여기서 번뜩해야 한다. 우리는 OAuth2를 만들면서 별도의 application-oauth.properties를 생성했었다.
테스트코드에서는 이 properties를 못 찾는 것 같다.
해결방법은 책에서는 별도의 테스트용 properties를 'src/test/resources' 경로로 추가해서 작성하도록 가이드하고 있다.
일전에 다른 습작 프로젝트를 진행했을때도 테스트를 위한 별도의 properties를 작성했던 기억이 떠올라서 별 어려움 없이 생성해주었다.
개선된 코드를 통해서 다시 통합 테스트를 수행해보자.
PostApiControllerTest가 정상적으로 이제 패스가 되기 시작했다.
남아있는 HelloControllerTest를 개선해보자.
Error creating bean with name 'securityConfig' defined in file [C:\Users\kdh\Documents\spring-aws-study\build\classes\java\main\com\kdh85\book\springawsstudy\config\auth\SecurityConfig.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.kdh85.book.springawsstudy.config.auth.CustomOAuth2UserService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
스프링 시큐리티를 추가하면서 만든 SecurityConfig 에 대한 Bean 생성 관련 문제로 보인다.
초반에 우리는 @WebMvcTest를 사용할 경우의 compoent scan 기준을 확인했었다.
해당하는 테스트코드에는 SecurityConfig 설정이 필요하지 않은 테스트다.
이런 경우 scan 대상에서 제외를 해야 하는데 이럴때 사용하는 옵션이
@WebMvcTest 의 excludeFilters 이다.
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = SecurityConfig.class)
를 설정해주자.
그리고 각 테스트메소드에도 기본적으로 @WithMockUser(roles = "USER")를 할당해야 스프링 시큐리티에서 정상적으로 테스트가 수행가능해지는 점을 잊지말자.
이제 모든 테스트가 전부 정상적으로 통과하게 되었다.
TDD 교육을 받을때 포비님께서 하신 말씀이 떠올랐다.
우리는 흔히 프로덕션 코드만을 리팩토링해야 한다고 생각하지만
사실이 아니다.
오히려 테스트코드를 더 많이 리팩토링해야 하고 개선을 해야 유지보수에 유리하다.
이 말이 정말 잘 와닿은 케이스였다고 생각한다.
MockMvc를 이용하는 테스트코드 작성에 조금씩 익숙해지기 시작한 것 같다.
정말 잘 읽고 갑니다~