Mockito初探
Mockito
可以改变一个类或者对象的行为,能够让我们更加专注地去测试代码逻辑,省去了构造测试数据所花费的努力。
概念介绍
-
Mock :可分为两种类型,一种是 Class Mock,另一种是 Partial Mock(Mockito 叫 spy)实例Mock对象。
- Class Mock
- Partial Mock (spy)
-
Stub:定义 mock 对象方法(method)的行为 。
- Stubbing
- Stubber
- Answer
-
Verify:验证Stub行为
- times()
- never()
- atLeastOne()
- atLeast()
- atMost
- calls
- only
- timeOut
- after
-
Argument Matcher:参数类型定义,结合Stubbing使用,定义参数类型。同时支持lambda
- 具体列表查看ArgumentMatchers
MOCK
- 示例代码
import static org.mockito.Mockito.*;
public class MockitoTest {
@Test
public void test() {
//Mock:定义Class Mock对象,这里返回的mockedList完全失去了原来的行为
List mockedList = mock(List.class);
//Stub:未定义,返回默认值false
System.out.println(mockedList.add("a"));
//校验Stub行为合法性。如果是add("b"),则不通过。因为没有定义add("b")的行为
verify(mockedList).add("a");
}
@Test
public void spytest() {
List list = new LinkedList();
//定义Partial Mock 实例Mock对象
List spy = spy(list);
//定义stub返回false
when(spy.add("a")).thenReturn(false);
//返回false 定义了stub
System.out.println(spy.add("a"));
//为定义add("b")行为,则调用真实方法
System.out.println(spy.add("b"));
//校验
verify(spy).add("a");
}
}
- Class Mock 和 Spy的区别
mock源码
1:
@CheckReturnValue
public static <T> T mock(Class<T> classToMock) {
//注意withSettings,配置默认返回方式为返回java相关类型的默认值
return mock(classToMock, withSettings());
}
@CheckReturnValue
public static MockSettings withSettings() {
return new MockSettingsImpl().defaultAnswer(RETURNS_DEFAULTS);
}
2:
@CheckReturnValue
public static <T> T mock(Class<T> classToMock, MockSettings mockSettings) {
return MOCKITO_CORE.mock(classToMock, mockSettings);
}
spy源码
@CheckReturnValue
public static <T> T spy(T object) {
return MOCKITO_CORE.mock((Class<T>) object.getClass(), withSettings()
.spiedInstance(object)
//默认执行对象的真实方法
.defaultAnswer(CALLS_REAL_METHODS));
}
跟踪源码得到结论,spy和mock方法最大的区别是配置不同的Mock对象MockSetting。使其行为不一样。
Stub
- 示例代码
@Test
public void stubtest() {
ArrayList a=new ArrayList();
List mock=spy(a);
//List mock=mock(ArrayList.class);
//这里如果是 spy的类型 会执行真实方法 add("a")
when(mock.add("a")).thenReturn(false);
doThrow(new RuntimeException()).when(mock).add("b");
doReturn(false).when(mock).add("c");
doAnswer(new Answer() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
return false;
}
}).when(mock).add("d");
//doCallRealMethod不能定义抽象方法,如是通过mock创建需要配置构造对象
//OtherAbstract spy = mock(OtherAbstract.class, withSettings().useConstructor().defaultAnswer(CALLS_REAL_METHODS));
doCallRealMethod().when(mock).add(0,"e");
//doNothing只能定义void方法
doNothing().when(mock).clear();
System.out.println(mock.add("a"));
System.out.println(mock.add("c"));
System.out.println(mock.add("d"));
mock.add(0,"e");
mock.clear();
System.out.println(mock.size());
System.out.println(mock.add("b"));
}
可通过when|doThrow|doReturn|doAnswer|doCallRealMethod|doNothing定义stub行为,注意spy与class mock使用是的区别。
Argument Matcher
- 实例代码
@Test
public void argTest() {
List mock = mock(List.class);
//通过Argument Matcher anytring()定义参数,提供有anyList,anyBoolean等等比较多不一一列举
when(mock.add(anyString())).thenReturn(false);
System.out.println(mock.add("a"));
System.out.println(mock.add("b"));
List list = new ArrayList();
List spy = spy(list);
//支持lambda
when(spy.add(argThat((String e) -> e.length() < 3))).thenReturn(false);
System.out.println(mock.add("a"));
System.out.println(mock.add("b"));
System.out.println(spy.add("b"));
System.out.println(spy.add("b22"));
}
Argument Matcher 用于定义stubing传入的参数,默认封装了anyString()等常用的测试参数,可以自定义创建需要的测试的参数范围。
Verify
- 实例代码
//verify(mock).someMethod() 相当于 verify(mock, times(1))
@Test
public void argVerify() {
List mock = mock(List.class);
when(mock.add(anyString())).thenReturn(false);
System.out.println(mock.add("a"));
System.out.println(mock.add("b"));
List list = new ArrayList();
List spy = spy(list);
when(spy.add(argThat((String e) -> e.length() < 3))).thenReturn(false);
System.out.println(mock.add("a"));
System.out.println(mock.add("b"));
System.out.println(spy.add("b"));
System.out.println(spy.add("b22"));
// times校验行为调用次数,上面代码块中mock.add("a")执行了两次,如果校验times(1),则不通过
//times提供了多个方法支持atLeastOnce()等
verify(mock,times(2)).add("a");
verify(mock,times(2)).add("b");
verify(spy).add("b");
verify(spy).add("b22");
}
用于校验mock对象是否执行了你想要的行为
网友评论