Spring Boot事件监听器测试疑问:为何verify未捕获handler方法的执行?
问题原因分析
嘿,这个问题我之前也碰到过!核心原因是:你手动创建的EventHandler mock对象,和Spring容器中实际处理事件的EventHandler实例根本不是同一个。
具体来说:
- 你用
mockkClass(EventHandler::class)造了个mock,但这个对象压根没被注册到Spring容器里; - Spring启动时已经实例化了真实的
EventHandlerBean,当你调用publisher.publishEvent(event)时,是容器里的真实Bean在执行handler方法; - 你最后去verify的是自己造的那个“孤儿”mock,它从来没被调用过,断言自然失败啦。
解决方案
针对这个场景,有两种常用的正确做法:
方法一:用@MockBean替换容器中的真实Bean
@MockBean会自动替换Spring容器中对应类型的Bean为mock实例,这样事件触发时就会调用这个mock对象,verify就能正常捕获调用:
@SpringBootTest class SendWelcomeEmailTest { @Autowired lateinit var publisher: ApplicationEventPublisher // 用@MockBean替换容器中的EventHandler为mock实例 @MockBean lateinit var eventHandler: EventHandler @Test fun test(){ val someObject = SomeObject() val event = SomeEvent(this, someObject) publisher.publishEvent(event) // 直接verify容器中的mock实例 verify { eventHandler.handler(any()) } } }
方法二:用@SpyBean包装真实Bean(需要验证真实逻辑+调用次数时用)
如果你既想让真实的handler方法执行,又要验证它是否被调用,可以用@SpyBean:
@SpringBootTest class SendWelcomeEmailTest { @Autowired lateinit var publisher: ApplicationEventPublisher // 包装容器中的真实EventHandler为spy实例 @SpyBean lateinit var eventHandler: EventHandler @Test fun test(){ val someObject = SomeObject() val event = SomeEvent(this, someObject) publisher.publishEvent(event) // 验证spy实例的handler方法被调用 verify { eventHandler.handler(any()) } } }
补充说明
@MockBean和@SpyBean都是Spring Boot Test提供的注解,专门用于在测试中替换或增强容器中的Bean;- 手动创建的mock对象如果没有被注册到容器,Spring的事件机制根本不会感知到它,自然不会调用它的方法。
内容的提问来源于stack exchange,提问作者user15941734
相关产品推荐
相关产品推荐

