如何使用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
相关产品推荐
相关产品推荐

