Mockito是一个模拟框架,可让您使用简洁的API编写漂亮的测试。 它偏向于最低规格,使不同的行为看起来有所不同,并显示清晰的错误消息。
创造嘲弄
要使用Mockito创建模拟,只需使用@Mock
注释模拟,然后调用MockitoAnnotations.initMocks(this)
。
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;public class FooClassTest {@Mock mockFoo;public void setUp() {MockitoAnnotations.initMocks(this);...}...
}
存根值
存根值可以刺激现有代码的行为,或临时替代尚待开发的代码。 默认情况下,对于所有返回值的方法,mock返回null,空集合或适当的原始/原始包装器值(例如:0,false,…)。 您可以按以下方式覆盖存根值。 一旦存根,该方法将始终返回存根值,而不管它被调用了多少次。 对于具有无效返回值的方法,通常不需要将其存根。
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.when;
...
// a method that returns values
when(mockFoo.someCall()).thenReturn(someValue);
when(mockFoo.someCall()).thenThrow(new FooException());
// a method with a void return
doThrow(new FooException()).when(mockFoo).voidMethodThatThrows();
验证方法是否被调用
// call the subject under test
verify(mockFoo, times(2)).someCall();
verify(mockFoo).someCall();
verify(mockFoo).callWithVoidReturnType();
“粗略”和“验证”有什么区别? 简而言之,对于您并不真正关心的项目,应使用“存根”,但它们必须通过测试。 相反,应使用“验证”来验证行为。
验证单个对象的调用顺序
InOrder order1 = Mockito.inOrder(mockFoo);
order1.verify(mockFoo).firstCall();
order1.verify(mockFoo).thirdCall();InOrder order2 = Mockito.inOrder(mockFoo);
order2.verify(mockFoo).secondCall();
order2.verify(mockFoo).fifthCall();
验证跨多个对象的调用顺序
Foo mockFoo = Mockito.mock(Foo.class);
Bar mockBar = Mockito.mock(Bar.class);// call the subject under test
InOrder order = Mockito.inOrder(mockFoo, mockBar)
order.verify(mockFoo).firstCall();
order.verify(mockBar).secondCall();
验证仅进行了预期的呼叫
通常,不再进行交互的测试应该很少。
// call the subject under test
verify(mockFoo).expectedCall();
verify(mockFoo).someOtherExpectedCall();
verifyNoMoreInteractions(mockFoo);
验证未拨打特定电话
测试未发出特定呼叫通常比检查“不再有呼叫”要好。
// call the subject under test
verify(mockStream, never()).close();
匹配器
当==
和equals
不能用于存根或验证时,我们可以将匹配器用于模拟方法参数。 如果您发现需要复杂的匹配器,请考虑简化您的测试对象或测试,或者考虑使用手工制作的假冒代替模拟。
import static org.mockito.Mockito.*;// Both of these forms use "equals"
when(mockFoo.set("blah", 2)).thenReturn(value);
when(mockFoo.set(eq("blah"), eq(2))).thenReturn(value);when(mockFoo.set(contains("la"), eq(2))).thenReturn(value);
when(mockFoo.set(eq("blah"), anyInt())).thenReturn(value);
when(mockFoo.set(anyObject(), eq(2))).thenReturn(value);
when(mockFoo.set(isA(String.class), eq(2))).thenReturn(value);
when(mockFoo.set(same(expected), eq(2))).thenReturn(value);ArgumentCaptor<String> sArg = ArgumentCaptor.forClass(String.class);
when(mockFoo.set(sArg.capture(), eq(2))).thenReturn(value);
...
// returns last captured value
String capturedString = sArg.getValue();
List<String> capturedStrings = sArg.getAllValues();
局部嘲弄
使用spy
或CALLS_REAL_METHODS
,您可能希望使用不调用现有方法或存根的备用存根语法: doReturn("The spy has control.").when(mockFoo).aMethod()
。
import org.mockito.Mockito;Foo mockFoo = Mockito.spy(new Foo()); // Note: instance, not class.
// Note: "when" calls the real method, see tip below.
when(mockFoo.aMethod()).thenReturn("The spy has control.");
// call the subject under test
verify(mockFoo).aMethod();
// Verify a call to a real method was made.
verify(mockFoo).someRealMethod();
// Alternative construct, that will fail if an unstubbed abstract
// method is called.
Foo mockFoo = Mockito.mock(Foo.class, Mockito.CALLS_REAL_METHODS);
翻译自: https://www.javacodegeeks.com/2014/09/mockito-101.html