1. 概述
在这个简短教程中,我们将专注于使用Mockito模拟void
方法。
与之前关于Mockito框架的文章(如Mockito验证、Mockito的When/Then和Mockito的Mock方法)一样,下面的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 whenAddCalled_thenVerified() {
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
void whenAddCalled_thenVerified() {
MyList myList = mock(MyList.class);
myList.add(0, "");
verify(myList, times(1)).add(0, "");
}
doThrow()
会抛出一个异常:
@Test
void givenNull_whenAddCalled_thenThrowsException() {
MyList myList = mock(MyList.class);
assertThrows(Exception.class, () -> {
doThrow().when(myList).add(isA(Integer.class), isNull());
});
myList.add(0, null);
}
我们将在下面讨论doAnswer()
。
3. 参数捕获
使用doNothing()
覆盖默认行为的一个原因是捕获参数。
在上述例子中,我们使用verify()
方法检查传递给add()
的方法参数。
然而,我们可能需要捕获参数并对其做更多的处理。
在这种情况下,我们像上面那样使用doNothing()
,但使用一个ArgumentCaptor
:
@Test
void givenArgumentCaptor_whenAddCalled_thenValueCaptured() {
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. 回答对void
的调用
一个方法可能执行的不仅仅是添加或设置值的简单行为。
对于这些情况,我们可以使用Mockito的Answer
来添加我们需要的行为:
@Test
void givenDoAnswer_whenAddCalled_thenAnswered() {
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");
}
如Mockito的Java 8特性所述,我们使用带有Answer
的lambda来为add()
定义自定义行为。
5. 部分模拟
部分模拟也是一个选择。Mockito的doCallRealMethod()
也可以用于void
方法:
@Test
void givenDoCallRealMethod_whenAddCalled_thenRealMethodCalled() {
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项目中找到。