개발 지식/Test

[Test] Interceptor 적용 후 기존 컨트롤러 테스트 깨짐

서하빈 2024. 1. 10. 11:34

에러 로그

Parameter 0 of constructor in com.example.workingbook.interceptor.WebMvcConfig required a bean of type 'com.example.workingbook.device.repository.DeviceRepository' that could not be found.

 

- 로그를 봤을 때 해당 인터셉터를 등록하는 설정 파일에서 DeviceRepository를 사용하고 있는데 컨트롤러 테스트에서 사용하는 @WebMvcTest에는 Repository 계층의 빈들은 등록하지 않기 때문에 발생한 문제이다.

 

 

해결 방법

1. 해당 인터셉터를 MockBean으로 대체

- 아예 인터셉터가 동작하지 않게 적용

 

- 이렇게 하는 경우 원래의 인터셉터가 그대로 동작하게 된다. 그 이유는 WebMvcConfig에서 new 키워드를 통해 인터셉터를 생성하고 있기 때문에 스프링 빈으로 인터셉터가 직접 등록되는 방식이 아니며 따라서 MockBean으로 대체되지 않는다.

 

 

여기에서도 인터셉터가 동작되지 않게 하는 방법으로 두 가지 방법이 있다.

- WebMvcConfig를 MockBean으로 대체

- 여기에서는 이 방법을 선택하였음.

 

- HandleDeviceIdInterceptor를 빈으로 등록 후 MockBean으로 대체

- HandleDeviceIdInterceptor를 빈으로 등록

 

- MockBean 주입 시 반드시 상위 인터페이스 타입으로 주입하여야 한다.

 

 

2. 인터셉터 동작에 맞게 컨트롤러 테스트를 수정

- mockMvc 요청 헤더에 deviceId를 넣고 deviceRepository의 findById 메서드만 given을 통해서 대체하는 방식으로 적용

 

- 실제로 인터셉터가 동작함을 확인할 수 있다.

- 컨트롤러의 기능만을 테스트하기 위해서는 인터셉터도 MockBean으로 대체하는 방법이 맞는 것 같다. @SpringBoot를 이용한 통합 테스트에서 이 방식을 사용하는 것이 좋을 듯 하다.

 

 

결론

WebMvcConfig를 MockBean으로 추가하여 인터셉터가 동작하지 않도록 하는 방법을 적용하는 것이 컨트롤러만 테스트하는 슬라이스 테스트에 더 적합하다고 판단하여 해당 방법을 적용하였다. 추후에 모든 컨트롤러 테스트에 전역적으로 해당 설정을 적용하는 방식을 사용하는 것이 더 좋을 것 같다.