[1/24 TIS] OAuth 2.0 적용에 따른 테스트 코드 수정
OAuth를 적용하면서 Spring Secuirty의 filter chain에 OAuth와 관련한 친구들이 추가되었다. 문제는 이게 테스트 코드에도 영향을 준다는 점이었다.
기존의 API계층에 대한 테스트 코드에는 SecurityAutoConfig 파일을 제외하는 설정이 되어있었다. Spring Security를 테스트하고 싶으면 아예 Integration test를 진행하고, API계층에서는 들어온 DTO가 출력 결과와 같게 출력되는지만 확인하고 싶었기 때문이다. 그런데 OAuth가 추가되면서, 잘 돌아가던 테스트가 돌아가지 않게 되었다.
아래는 에러 코드인데, 너무 길어서 첫 줄만 따왔다.
Consider defining a bean of type 'org.springframework.security.config.annotation.web.builders.HttpSecurity' in your configuration. 2024-01-24 23:14:23.336 ERROR 14992 --- [ Test worker] o.s.test.context.TestContextManager :
Caught exception while allowing TestExecutionListener [org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener@5bd1ceca] to prepare test instance [tdd.groomingzone.post.freeboard.adapter.in.web.PostFreeBoardControllerTest@c190cfc]
java.lang.IllegalStateException: Failed to load ApplicationContext
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'oauth2SecurityFilterChain' defined in class path resource [org/springframework/boot/autoconfigure/security/oauth2/client/servlet/OAuth2WebSecurityConfiguration$OAuth2SecurityFilterChainConfiguration.class]: Unsatisfied dependency expressed through method 'oauth2SecurityFilterChain' parameter 0; nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.security.config.annotation.web.builders.HttpSecurity' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
좀 읽어보니, @WebMvcTest를 사용한 테스트를 수행하는데 필요한 Application Context를 Load하는 과정에서 oauth2SecurityFilterChain이라는 Bean을 등록하는데 필요한 HttpSecurity 타입의 파라미터가 Bean으로 등록되지 않았다는 말인 것 같았다.
문제는 HttpSecurity를 Bean으로 등록하는 방법이 마땅치가 않았다. 공식문서에 적혀있는 방법을 사용해도 계속 다른 부분에서 문제가 발생했다.
그래서 처음에는 어쩔 수 없이 모든 @WebMvcTest를 @SpringBootTest로 전환해서 사용하는 방법을 선택했다. 문제는 이렇게 진행하면, 삭제, 수정, 조회의 기능을 테스트 할 때마다 회원을 저장하고, 특정 객체를 저장하는 과정을 거쳐야했다. 이렇게 되면 빌드 단계에서 지나치게 많은 시간이 소요될 것이 분명했고, 다른 방법을 찾아야했다.
에러 코드를 다시 읽어보니, 결국 Bean이 하나 부족한 것이었다. 부족한 Bean은 Spring Security에 OAuth를 적용하기 위해서 필요한 Bean이었다. @WebMvcTest를 붙여서 API계층의 테스트 코드를 작성한 이유는 Spring Security를 제거하고 API계층의 비즈니스 코드만 테스트 하고싶어서였다. 그러면 굳이 Configuration을 이용해 HttpSecurity Bean과 oauth2... Bean을 등록해야하나 싶었다.
그럴거면 그냥 MockBean으로 SecurityFilterChain만 등록해주면 되는거 아닌가? 싶어서 바로 적용했다.
테스트 자체는 성공적으로 수행됐다. 필요한 Bean을 가짜 객체로 만들어줬고, 어짜피 oAuth를 사용하지 않으니 별도로 행위를 Mocking하지 않아도 됐다.
테스트 자체는 통과가 됐지만 이게 맞는 방법인가에 대한 고민은 남는다. 아예 OAuth 설정도 빼거나, 아니면 TestConfiguration에서 Bean을 등록하는 방법을 내가 못찾은 건 아닐지싶긴하다. 물론 거의 이틀을 이것만 찾아보긴 했는데 혹시 모르니까... 좀 더 공부해봐야겠다.