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

如何使用Mockito模拟Java中void方法的内部行为?

问题描述

我有遵循访问者设计模式的接口:

public interface VisitorContext
{
    POJOClass getMethod(); // 该方法返回POJOClass对象
}
public interface Visitor
{
    void before(VisitorContext visitorContext);
}

我想在独立的测试类中测试这些接口,以下是我的测试代码片段:

public class EngineTest
{
    private VisitorContext visitorContext = Mockito.mock(VisitorContext.class);
    private Visitor testVisitor = Mockito.mock(Visitor.class);
    private List<VisitorContext> beforeList = new ArrayList<>();

    @Test
    public void doTest() // 修正:原代码缺少void修饰符
    {
        when(testVisitor.before(any(VisitorContext.class))).then(beforeList.add(visitorContext));
    }
}

运行时出现错误:

'when(T)' in 'org.mockito.Mockito' cannot be applied to '(void)'

我想模拟Java中void方法的内部行为,但不知道该怎么操作,请问该如何实现?

解决方案

Mockito的when()方法只支持处理有返回值的方法,对于无返回值的void方法,得用doAnswer()这类专门的API来定制行为。

要实现调用before()时把参数加入列表的需求,用doAnswer()来写自定义逻辑就行,修改后的测试代码如下:

@Test
public void doTest() {
    // 给before方法定制执行逻辑
    doAnswer(invocation -> {
        // 获取调用方法时传入的VisitorContext参数
        VisitorContext context = invocation.getArgument(0);
        beforeList.add(context);
        return null; // void方法返回null就可以
    }).when(testVisitor).before(any(VisitorContext.class));

    // 调用要测试的方法
    testVisitor.before(visitorContext);

    // 验证列表是否正确添加了元素
    assertEquals(1, beforeList.size());
    assertEquals(visitorContext, beforeList.get(0));
}

注意事项:

  • doAnswer()里可以用Lambda表达式快速实现Answer接口,通过invocation.getArgument(index)拿到方法调用时的参数,然后执行你想要的操作。
  • 语法上要注意:doAnswer(...)写在前面,后面跟when(mock).method(...),这是Mockito处理void方法的固定写法。
  • 别忘了主动调用before()方法,再验证结果,确保你的自定义逻辑真的生效了。

如果只是想验证before()方法有没有被调用过,直接用verify()更简单:

testVisitor.before(visitorContext);
verify(testVisitor).before(any(VisitorContext.class));

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 20:23:29