You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Mockito正确测试带回调的Kafka Producer send方法?

解决Mockito测试中回调分支未执行的问题

你的问题其实有两个核心点需要解决:回调函数没有被主动触发,以及静态Logger无法被Mock注入,我一步步给你讲清楚怎么调整:

1. 为什么回调没进入if分支?

Mockito默认情况下,当你mock像producer.send()这类带回调参数的方法时,它只会按你设定的返回值返回(比如你这里的thenReturn(null)),但不会主动执行你传入的Callback接口的onCompletion方法。所以你的if/else分支根本没机会运行,自然就verify不到日志输出了。

解决这个问题的核心是:拦截send方法的调用,手动取出回调对象并触发它。

2. 为什么Logger的verify会失败?

你原类中的LOGGER是static final类型的静态字段,@InjectMocks只能注入实例字段,管不到静态属性。所以你@Mock的logger根本没被用到,原类还是用的真实Logger实例,这也是verify失败的隐藏原因。

3. 修改后的测试代码

下面是调整后的完整测试代码,我加了详细注释:

@RunWith(MockitoJUnitRunner.class)
public class SomeClassTest {
    @InjectMocks
    private SomeClass someclass;

    @Mock
    private Producer<String, SpecificRecord> producer;

    @Mock
    private SpecificRecord message;

    @Mock
    private Logger logger;

    @Test
    public void sendMessageTest() {
        // 第一步:Mock静态的Logger.Factory,让它返回我们的mock logger
        try (MockedStatic<Logger.Factory> mockedLoggerFactory = Mockito.mockStatic(Logger.Factory.class)) {
            mockedLoggerFactory.when(() -> Logger.Factory.getLogger(SomeClass.class))
                               .thenReturn(logger);

            // 第二步:拦截producer.send的调用,手动触发回调
            doAnswer(invocation -> {
                // 取出方法调用时传入的第二个参数——也就是Callback对象
                Callback callback = invocation.getArgument(1);
                // 调用回调的onCompletion方法,传入null作为exception,触发OK分支
                callback.onCompletion(null, null);
                // send方法返回Future,这里返回null即可
                return null;
            }).when(producer).send(any(ProducerRecord.class), any(Callback.class));

            // 预设flush方法什么都不做
            doNothing().when(producer).flush();

            // 执行测试方法
            someclass.sendMessage("topic", message, new HashMap<String, String>());

            // 验证日志是否被正确调用
            verify(logger).info("OK");
        }
    }
}

4. 扩展:测试异常分支

如果想测试exception != null的NOK分支,只需要修改回调触发的代码:

// 在doAnswer里传入一个非null的Exception
callback.onCompletion(null, new RuntimeException("测试异常"));

// 然后验证NOK日志
verify(logger).info("NOK");

注意事项

  • 这个方案要求你使用Mockito 3.4.0及以上版本,因为mockStatic是从这个版本开始引入的官方静态Mock功能。如果你用的是老版本,可以考虑升级Mockito,或者用PowerMock来实现静态Mock。
  • 如果需要更精确的参数匹配,比如验证ProducerRecord的topic、key等是否正确,可以把any(ProducerRecord.class)换成argThat来做自定义匹配。

内容的提问来源于stack exchange,提问作者oitathi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 06:27:48