用 Mockito 模拟 Void 方法
1. 概述
这个教程,我们主要关注如何使用Mockito模拟void方法
使用一个MyList类,来作为被测试的类
public class MyList extends AbstractList<String> {
@Override
public void add(int index, String element) {
// no-op
}
}
2. 简单的模拟和验证
Void 方法可以与 Mockito 的 doNothing()、 doThrow()和 doAnswer()方法一起使用,使模拟和验证更加直观:
@Test
public void whenAddCalledVerified() {
MyList myList = mock(MyList.class);
doNothing().when(myList).add(isA(Integer.class), isA(String.class));
myList.add(0, "");
verify(myList, times(1)).add(0, "");
}
但是,doNothing()是 Mockito 的 void 方法的默认行为。
这个版本的whenAddCalledVerified()完成了与上面一个相同的事情:
@Test
public void whenAddCalledVerified() {
MyList myList = mock(MyList.class);
myList(0, "");
verify(myList, times(1)).add(0, "");
}
Dothrow()生成一个异常:
@Test(expected = Exception.class)
public void givenNull_AddThrows() {
MyList myList = mock(MyList.class);
doThrow().when(myList).add(isA(Integer.class), isNull());
myList.add(0, null);
}
我们接下来讨论doAnswer()
3. 捕获参数
使用 doNothing()覆盖默认行为的一个原因是捕获参数。
在上面的示例中,我们使用 verify()检查传递给 add()的参数。
我们可能需要捕获这些参数,可以像上面一样使用 doNothing() ,再加一个 ArgumentCaptor:
@Test
public void whenAddCalledValueCaptured() {
MyList myList = mock(MyList.class);
ArgumentCaptor<String> valueCapture = ArgumentCaptor.forClass(String.class);
doNothing().when(myList).add(any(Integer.class), valueCapture.capture());
myList.add(0, "captured");
assertEquals("captured", valueCapture.getValue());
}
4. Answering a Call to Void
方法可能执行比仅仅增加或设置值更复杂的行为。 对于这些情况,我们可以使用 Mockito 的回答来添加我们需要的行为:
@Test
public void whenAddCalledAnswered() {
MyList myList = mock(MyList.class);
doAnswer(invocation -> {
Object arg0 = invocation.getArgument(0);
Object arg1 = invocation.getArgument(1);
assertEquals(3, arg0);
assertEquals("answer me", arg1);
return null;
}).when(myList).add(any(Integer.class), any(String.class));
myList.add(3, "answer me");
}
我们使用带有 Answer 的 lambda 来定义 add()的定制行为。
5. 部分模拟
部分模拟也是一个选择, Mockito 的 doCallRealMethod()可用于 void 方法:
@Test
public void whenAddCalledRealMethodCalled() {
MyList myList = mock(MyList.class);
doCallRealMethod().when(myList).add(any(Integer.class), any(String.class));
myList.add(1, "real");
verify(myList, times(1)).add(1, "real");
}
这样,我们可以调用实际的方法并同时验证它。
6. 总结
这个教程,我们介绍了在使用 Mockito 进行测试时处理 void 方法的四种不同方法。
这些例子可以在这个 GitHub 项目中找到。