티스토리 뷰

이글은 Spring Boot 로 Test 작성시 @MockBean 이 제대로 동작하지 않는 삽질을 하게 되어 정리합니다.

 

새로운 조직에 와서 @MockBean 을 사용을 하여 IntegrationTest 를 작성 중이였는데, Mocking 이 제대로 동작을 하지 않아서 한참을 삽질을 하였다. 결론 부터 말하면 바로 이전팀에서도 동일한 삽질을 했었다. 하지만 똑같은 삽질을 하게 되어 이렇게 정리하게 되었다. 분명 나와 같은 실수를 하는 사람들이 있을 지도 모르기에 기록으로 남기고자 한다.

왜 삽질을 했나?

 

Spring Boot 으로 DBUnit 을 이용하여 테스트를 작성할려고 하면 springtestdbunit/spring-test-dbunit 가이드대로 하게 된다. 그런데 @MockBean 이 동작 하지 않을 것이다. 내가 @MockBean 을 잘못 설정했는지 수도없이 검증해보게 되었다. 그래서 찾다보니, TestExecutionListner 를 Custom 하게 정의해서  문제가 되었다는 걸 알게되었고, spring.factroies 파일을 통해서 자동으로 DbUnitTestExecutionListener 가 로딩되도록 설정했었다. 근데 새로운 팀에 왔는데, 또 동일한 삽질을 했다. 2번이상 실수를 반복하지 않기 위해  spring-boot-dbunit-stater 패키지를 만들어 보게 되었다.

 
자료를 찾다가 알게 되었는데 https://github.com/Freeongoo/spring-boot-dbunit 에는 친절하게 @MockBean 사용시 주의하라고 나와 있다.

 

DBUnit 이란?
 
백기선님의 Youtube 영상에서도 설명하고 있지만 그리고 영상에서 보면 여러 TestFramework 을 소개하는 데, 그중에 DBUnit 이라는게 있다. DBUnit 은 DB  Query를 테스트할 수 있도록 도와주는 도구이다. 현재 정식(?) repository 는 더이상 관리가 되지않아 다른분이 Fork 하여서 관리를 하고 있는 상태다. 그런데 대부분의 예제는 기존 관리되지 않고 있는 코드를 베이스로 하고 있긴 하다.

 

본론으로 들어가 보면 @TestExecutionListeners 이 아래와 같이 설명하고 있다. 디폴트값이 replace 라는 것이다. 즉, spring-boot-test 에서 기본적으로 Loading 해주는 TestExecutionListeners 들이 무시된다.

The merge mode to use when @TestExecutionListeners is declared on a class that does not inherit listeners from a superclass.
Can be set to MERGE_WITH_DEFAULTS to have locally declared listeners merged with the default listeners.
The mode is ignored if listeners are inherited from a superclass.
Defaults to REPLACE_DEFAULTS for backwards compatibility.
 
그래서 아래와 같이 해주면 해결이 된다.

 

@TestExecutionListeners(listeners = { DependencyInjectionTestExecutionListener.class,
    DirtiesContextTestExecutionListener.class,
    TransactionalTestExecutionListener.class,
    DbUnitTestExecutionListener.class }, mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS))
 
근데 위와 같이 매번반복적으로 해주는 것도 다소 귀찮은 일이고 중복이 발생한다. 그래서 단순하게는 AbstractIntegrationTest.java 로 빼서 하면 되겠지만, 좀더 간단하게 starter package 를 만들어서 자동으로 TestExecutionListener 가 loading 될수 있도록 바꿔 보았다. 따로 설정해 줄건 없고 아래와 같이 stater package 만 의존성에 추가 해주면 끗!
allprojects {
   repositories {
       maven { url 'https://jitpack.io' }
   } 
}

dependencies {
    testImplementation 'com.github.anyjava.spring-boot-dbunit:spring-boot-dbunit-starter:1.0.0'
}
  • JitPack 이 살짝 느린 느낌이 있어서 maven repo 에 배포하도록 바꿔 봐야할 듯..;;
아래 Github 에 가면 전체 소스를 확인 할 수 있다.
Spring boot starter 로 패키징하는건 그렇게 어렵지 않았다. 사실 Spring Autoconfiguration 이 어떻게 동작하는지 이해하는게 더 중요했던것 같다. 간단하게 설명하면, META-INF/spring.factories 에 추가해야할 DbUnitTestExecutionListener 만 추가해 주었다.
다만, JitPack 으로 배포하는데 더 많은 삽질을 하게 된듯 하다. (아래 참고자료 링크로 내가 보고 따라한 링크를 남기도록 한다) 

 

마치며
 
Spring Boot 을 사용하면 정말 매직이 많이 발생한다. 내가 모르는 곳에서 자동으로 설정해주는 부분이 많은데, 사용하면 할 수 록 이것들을 잘 사용해야겠다고 생각했다. 그리고 잘안되는 게 있을대 끝까지 파고들어 원인이 무엇인지를 명확히 알게되고 다시 실수하지 않도록 정리하는 것 또한 중요하다고 생각했다.
 
 
 
참고자료
 

 

 
 
댓글
댓글쓰기 폼