标签(空格分隔): 单元测试
Mockito的使用(kotlin坑多建议勿用)
导入Mockito的依赖
testCompile ‘org.mockito:mockito-core:2.7.6’1
2
3
4
5
6
7
8
9
10
11
12
13
14@Mock
private List data = new ArrayList<>();
@Before
public void setUp(){
MockitoAnnotations.initMocks(this);
//初始化Mock注解生成的对象,比如Mock对象,ArgumentCaptor等
List datas = Mockito.mock(List.class);
//创建Mock对象,与 @Mock 注解同理
ArgumentCaptor captor = ArgumentCaptor.forClass(String.class);
//创建ArugmentCaptor [email protected]
//后面会讲解ArgumentCaptor
}
验证调用,次数1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19@Test
public void TestStudy(){
datas.add("AAA");
datas.add("BBB");
datas.clear();
verify(datas).clear();
// any 有很多方法 可以匹配任意参数 比如 anyInt()
verify(datas,times(2)).add(anyString());
//调用两次
verify(datas,never()).addAll(any(Collection.class));
//从不调用
verify(datas,atLeast(2)).add(anyString());
//至少调用2次
verify(datas,atMost(2)).add(anyString());
//至多调用3次
}
修改行为1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39@Test
public void testReturn(){
when(datas.get(anyInt())).thenAnswer(new Answer() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
Integer index = invocation.getArgument(0);
return "YOUR INDEX IS : NO." + index;
}
});
//获取方法的参数并返回参数组成的字符串
when(datas.get(255))
.thenReturn("FIRST INVOKE GET(255)")
.thenReturn("SECOND INVOKE GET(255)")
.thenThrow(new RuntimeException("CAN'T GET MORE THAN THREE TIMES"));
//第一次返回第一句thenReturn,第二次第二句,第三次抛异常
doThrow(new RuntimeException()).when(datas).clear();
//清空数据则抛异常
System.out.println(datas.get(25));
System.out.println(datas.get(255));
System.out.println(datas.get(255));
System.out.println(datas.get(15));
// datas.clear(); 执行则会出错
// System.out.println(datas.get(255)); 执行则会出错
output:
YOUR INDEX IS : NO.25
FIRST INVOKE GET(255)
SECOND INVOKE GET(255)
YOUR INDEX IS : NO.1
}
```
#### 参数匹配@Test
public void testMatcher(){
//匹配包含HTTP的字符串
class HTTPStringmatcher implements ArgumentMatcher {
@Override
public boolean matches(String argument) {
return argument.contains("HTTP");
}
}
//当包含的参数有HTTP 则返回true
when(datas.contains(argThat(new HTTPStringmatcher()))).thenReturn(true);
//有时候 使用thenAnswer 比 Matcher 更加灵活
System.out.println(datas.contains("NOT CONTAINS"));
System.out.println(datas.contains("CONTAINS HTTP"));
output
false
true
}1
2#### 参数捕捉@Test
public void testCaptor(){
datas.add("ADD ONE STRING");
datas.add("ADD TWO STRING");
//验证时对方法的参数进行捕获
verify(datas,times(2)).add(stringCaptor.capture());
System.out.println(stringCaptor.getAllValues());
// output : [ADD ONE STRING, ADD TWO STRING]
}1
2#### 验证顺序@Test
public void testOrder(){
datas.add("A");
datas.clear();
datas.add("B");
InOrder order = inOrder(datas);
//顺序以及参数要完全匹配
order.verify(datas).add("A");
order.verify(datas).clear();
order.verify(datas).add("B");
}1
2#### 未验证互动@Test
public void redundant(){
datas.add("ONE");
datas.add("TWO");
verify(datas,times(2)).add(anyString());
verifyNoMoreInteractions(datas);
//检查未验证的互动
//上面的例子 验证通过
// datas.add(“C”);
// verifyNoMoreInteractions(datas);
// 加上上面两行则不通过,因为add(“C”)未被verify}1
2#### 零互动@Test
public void verifyZero(){
List a = mock(List.class);
List b = mock(List.class);
List c = mock(List.class);
a.add(1);
//验证对象都没有互动产生
verifyZeroInteractions(a,b,c);
//上述代码异常,因为list a 进行了操作,
}1
2#### 清除mock@Test
public void reset_mock(){
List list = mock(List.class);
when(list.size()).thenReturn(10);
list.add(1);
assertEquals(10,list.size());
//重置mock,清除所有的互动和预设
reset(list);
assertEquals(0,list.size());
}
Spy1
2#### 监控真实对象Spy@Test
public void spyTest() {
List list = new ArrayList<>();
List spy = spy(list);
//spy会调用真实对象的方法
doReturn("HELLO SPYER").when(spy).get(100);
//do...when 会避免调用真实对象的方法
when(spy.get(50)).thenReturn("OUT OF BOUNDS");
//when...then 会调用真实对象方法, 因为此时length为0 调用get(50)会异常
assertEquals(spy.get(100),"HELLO SPYER");
assertEquals(spy.get(50),"OUT OF BOUNDS");
}
`
利用mockito测试Presenter
在下篇文章讲述