ApplicationEventPublisher MockBean Injection 문제 해결 (@RecordApplicationEvents 활용)

2024. 4. 26. 17:42Backend/Spring

Meta: Spring Boot, ApplicationEventPublisher, MockBean, @RecordApplicationEvents, Spring Framework, Java, Backend, Test

Spring Boot에서 특정 비즈니스 로직 실행 시 이벤트 발행을 검증하기 위해 ApplicationEventPublisher를 @MockBean으로 주입하여 테스트하려고 했습니다.


특정 비즈니스 로직을 실행했을 때, 이벤트가 발행되는지 검증하기 위해 ApplicationEventPublisher를 @MockBean으로 주입하여 verify하고자 했습니다.

 

하지만 ApplicationEventPublisher를 MockBean 처리하여 SpringBootTest에 주입되게 의도하더라도

Mock 객체가 주입되지 않고 실제 ApplicationContext가 주입됩니다.

 

스프링 ApplicationContext 자체에 의해 구현된 ApplicationEventPublisher같은 경우에는 @MockBean을 직접 사용하는 것만으로 주입이 되지 않는데, 이는 Spring Framework Github에도 2016년 Issue로 올라왔습니다.

https://github.com/spring-projects/spring-boot/issues/6060

 

ApplicationEventPublisher mocked with MockBean is not injected in component under test · Issue #6060 · spring-projects/spring-

Version of Spring Boot: 1.4.0.M3 I have an integration test, annotated with @RunWith(SpringRunner::class) @SpringBootTest @AutoConfigureMockMvc and where I have @MockBean private lateinit var mockA...

github.com

 

 

@MockBean 주입이 되지 않는 이유는 ApplicationEventPublisher를 구현하는 Bean이

 

실제로 존재하는 Bean이 아니라 Spring 자체 컨텍스트 자체이기 때문입니다.

 

 

이 사안에 대해 

https://github.com/spring-projects/spring-framework/issues/18907

 

Make it possible to mock ApplicationEventPublisher in Spring Boot tests [SPR-14335] · Issue #18907 · spring-projects/spring-fr

Jean-Baptiste Nizet opened SPR-14335 and commented This is a followup to this bug posted on the Spring Boot project: spring-projects/spring-boot#6060 ApplicationEventPublisher, which is a direct de...

github.com

Spring에서는 ApplicationEventPublisher를 Mocking하는 방법이 아니라 spring framework 5.3.3부터 도입된 @RecordApplicationEvents를 사용하길 제안했습니다.

 

@RecordApplicationEvents

Spring 공식 Document를 보면 테스트 대상 클래스에 @RecordApplicationEvents를 두고

 

ApplicationEvents events를 Autowire하여 사용하라고 합니다.

 

IDE에서 autowire안된다고 하지만 잘 됩니다.

 

아래와 같이 활용할 수 있습니다.