SpringBoot Kafka契约测试中@SpyBean出现mock零交互是bug吗?
问题排查结论
该报错几乎不会是@SpyBean的Bug导致,绝大多数问题出在Kafka消费链路、Stub触发配置或者异步等待逻辑上,常见原因及修复方案如下:
- Stub触发配置不匹配
先核对契约定义中的trigger标签值是否和代码中调用的kafka-subscription-deletion-urm完全一致,同时确认契约中声明的Kafka Topic名称,是否和测试类@EmbeddedKafka注解中指定的Topic完全匹配,拼写、大小写错误都会导致消息发送到错误的Topic,监听器收不到消息。 - 消费者配置异常
检查contracttest环境下的Kafka消费者配置:一是消费者group-id是否和@AutoConfigureStubRunner中指定的consumerName = "urm"匹配;二是消息反序列化器是否支持将Stub发送的JSON/二进制内容反序列化为SubscriptionEvent类型,反序列化失败的消息会直接被丢弃,不会进入监听器方法。 - 监听器实例不匹配
你测试类指定的启动类是DummyApplication.class,确认该启动类的包扫描路径是否覆盖了OnSubscriptionEventListener所在的包。如果监听器没有被Spring容器扫描注册,你注入的@SpyBean根本不是实际监听Kafka的实例,自然不会捕获到方法调用。 - 缺少异步消费等待逻辑
Kafka消息消费是异步流程,你调用stubTrigger.trigger之后直接执行校验,很可能消息还没完成消费就触发了校验逻辑。可以替换校验代码为带超时的验证逻辑,给消费留足够的执行时间:// 最多等待3秒校验调用是否发生 verify(onSubscriptionEventListener, timeout(3000)).handleSubscriptionEvent(subscriptionArgumentCaptor.capture()); - 监听器方法不支持Spy
检查handleSubscriptionEvent是否被定义为final方法,Mockito默认无法Spy final方法,会导致方法调用记录无法被捕获,触发无交互的报错。
如果要确认是否是@SpyBean本身的问题,可以直接在测试方法中手动调用一次监听器方法,再执行校验:
@Test public void handle_subscription_deleted_event() { // 手动调用验证Spy是否正常 onSubscriptionEventListener.handleSubscriptionEvent(new SubscriptionEvent()); verify(onSubscriptionEventListener).handleSubscriptionEvent(any()); }
如果这段测试代码依然报相同错误,才需要排查@SpyBean的注入问题,否则可以确定是前面的消息链路问题。
内容的提问来源于stack exchange,提问作者Ray
相关产品推荐
相关产品推荐

