느려터진 Spring Rest Docs Test? SpringContext, @MockBean 없이 빠르고 효과적으로 사용하기
--
* 이 글은 특정 환경에서 SpringRestDocs 사용하는 분들에게 적절한 글입니다, 해당 사항이 없다면 안 보셔도 괜찮습니다.
- RestDocs Test를 통합 테스트 관점에서 작성하시는 분들
* 이런 분들은 보시면 도움이 됩니다.
- RestDocs Test를 http 통신 검증 + 문서화 관점으로 접근하시는 분
- RestDocs Test 작성할 때 ‘@MockBean’으로 mocking 하여 테스트를 작성하시는데 느려터져서 화나는 분
- 커밋 시마다 RestDocsTest로 문서화를 하게 구성했는데, 너무 느려서 속 터지시는 분
- ‘Spring Context Caching’ 을 쓰기 위해 모든 ‘@MockBean’을 모은 Test 용 ‘abstract class’ 를 만들어서 사용하시는 분
SpringRestDocs의 상세 사용법이나 장/단점은 검색 또는 레퍼런스를 참고해 주세요!
우선 SpringRestDocs 사용을 위해 일반적(?)으로 하는 구성을 살펴보겠습니다.

그리고 이런 Test를 작성하게 됩니다.

잘 동작하는 것 같고 당장엔 느린 것 같지도 않은데, 어떤 문제가 있을까요?
우선 문제의 핵심은 Test 시 ‘Spring Context’ 가 매번 생성되는 이슈입니다..
‘Spring Context’는 Test 간에 ‘@MockBean’의 구성이 다를 경우 Context가 새로 생성되면서 테스트가 수행됩니다.
예를 들어 ‘Spring Context’ 가 뜨는 데 1분이 걸리는 상황에서
‘@MockBean’ 구성이 모두 다른 테스트가 10개가 있다면, 기본적으론 모든 테스트를 수행하는 데 10분이 걸리게 됩니다.
이 시간을 단축할 수 있는 단순한 방법은 모든 RestDocs Test에 ‘@MockBean’ 구성을 동일하게 맞추는 겁니다.
RestDocs Test 관련하여 사용하는 모~든 ‘@MockBean’ 들을 한 개의 ‘abstract class’ 에 모아서 사용하면 ‘Spring Context’가 1개만 생성될 것이고 을 수행 시간을 단축할 수 있습니다.
그런데 이것은 문제가 없을까요?
매 Controller or Service 가 추가될 때마다 ‘abstract class’의 수정이 일어나고, 계속 계속 커지게 됩니다.
단일 Test 입장에서는 항상 불필요한 ‘@MockBean’ 덩어리들이 같이 수행되는 형태가 됩니다.
(닭 잡는데 청룡언월도…)
테스트 또한 우리가 책임지고 지속적으로 관리해야 하는 자원인데 좀 많이 아쉬운 부분이 있습니다.

그렇다면 어떻게 해결이 가능할까요?
핵심은 테스트하려는 ‘Controller’에 대해서 ‘Spring Context’ 없이 수행하는 것입니다.
이를 위한 기본 구성은 아래와 같습니다.
핵심적으로 볼 부분은 ‘mockMvc’ 함수에서 ‘controller’ 인자를 받고 있는 형태라는 것입니다.
그럼 이걸 활용한 테스트 코드는 어떨까요?
‘mockMvc’ 함수 호출 시에 테스트하려는 대상 ‘Controller’를 생성하고 적절한 Stub을 지정하고 있습니다.
(첫 예제부터 mock 과 stub에 대해서 할 말이 많지만 이 글에선 생략하겠습니다..)
이렇게 테스트할 경우 ‘Spring Context’ 없이 테스트가 가능해집니다.
또한, 이 테스트가 수행되는 시점에 오직 테스트가 필요한 대상들만 존재하게 됩니다.
(사용하지 않는 외부 Class, MockBean, Context 등등을 위한 별도의 의존성이 아예 필요 없습니다.)
여기까지 아주 간단하게 알아보았습니다.
그런데! 실제로 사용을 하려면 약간 더 디테일한 부분이 필요합니다. Spring에서 Controller를 쓸 경우 ‘ControllerAdvice’ 와 ‘ArgumentResolvers’ 등등이 필요하게 됩니다.
Controller를 생성해서 쓸 경우 이런 외부 구성이 정상 동작하지 않을 것이고,
RestDocs Test로 예외 케이스에 대한 문서를 작성하거나 프로덕션 코드와 동일한 구성을 테스트하지 못하게 되는 겁니다.
이러한 설정은 아래처럼 확장하여 구성이 가능합니다.
(다른 설정은 코드 작성해보시면서 보시면 충분히 커스텀 가능하실 것입니다.)
여기까지 RestDocs를 SpringContext 없이 테스트하는 방법을 알아보았습니다.
저의 경우 대부분 비즈니스 레이어는 이미 테스트 코드로 검증이 이미 되어있기 때문에, RestDocs Test를 ‘Http Layer + 문서화’ 관점으로 접근하며 테스트를 작성합니다.
RestDocs의 장/단점은 명확하지만, 제 생각엔 ‘지속 가능한 문서화’에서의 장점이 가장 큰 것 같습니다.
여기까지 읽어주셔서 감사드립니다 :D
좀 더 현실적인 예제가 있으면 좋을 것 같아서 아래 확장 판을 적습니다.
제가 실제 프로젝트에서 사용하는 버전입니다. ‘RestDocsTest’ 라는 ‘Base Class’를 생성 후 필요한 구성에 따라 ‘ApiRestDocsTest’ 로 한번 더 구조화하여 사용하는 방식입니다.
모듈 구성은 아래와 같이 접근합니다.
‘tests:api-docs’(테스트 지원 모듈) 모듈에 ‘RestDocsTst’ 가 존재하고,
‘http-api’(API Server) 모듈에 ‘ApiReestDocsTest’ 가 존재합니다.
‘ApiReestDocsTest’는 ‘http-api’의 런타임 설정과 완벽히 일치하는 설정을 갖고 있습니다.

만약 다른 형태와 구성을 가진 API 모듈이 나온다면 적절히 ‘RestDocsTest’ 를 확장하여 ‘고유한 Test 구성’을 만들 수 있습니다.