package com.wasu.mams.core.service.service.wimpl;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.InOrder;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.*;
/**
* 本文例子参考:https://wenku.baidu.com/view/8def451a227916888486d73f.html
*/
public class SimpleTest {
@Test
public void simpleTest(){
//创建mock对象,参数可以是类,也可以是接口
List<String> list = mock(List.class);
//设置方法的预期返回值
// when(mock.someMethod).thenReturn("value");
// 对于static final 修饰的方法不能执行when-thenReturn 方法
when(list.get(0)).thenReturn("helloworld");
when(list.get(1)).thenThrow(new RuntimeException("test excpetion"));
String result = list.get(0);
// mock对象一旦建立就会自动记录自己的交互行为,所以我们可以有选择的对它的交互行为进行验证
//验证方法调用(是否调用了get(0))
verify(list).get(0);
//junit测试
assertEquals("helloworld", result);
Iterator i = mock(Iterator.class);
/** 下面三种写法是一样的,都是第一次调用返回hello,第二次调用返回world **/
// 第一种写法
when(i.next()).thenReturn("hello").thenReturn("world");
// 第二种写法
when(i.next()).thenReturn("hello", "world");
// 第三种写法
when(i.next()).thenReturn("hello");
when(i.next()).thenReturn("world");
/** ---------------end--------------------- **/
// doNothing() 模拟不做任何返回(mock对象void方法默认返回)
doNothing().when(i).remove();
doThrow(new RuntimeException()).when(i).remove();
doNothing().doThrow(new RuntimeException()).when(i).remove();
}
@Test
public void argumentMatcherTest(){
List<String> list = mock(List.class);
when(list.get(anyInt())).thenReturn("hello","world");
String result = list.get(0)+list.get(1);
verify(list, times(2)).get(anyInt());
assertEquals("helloworld", result);
}
/**
* Mockito框架中的Matchers类内建了很多参数匹配器,而我们常用的Mockito对象就继承于Matchers。
* 这些内建的参数如anyInt匹配任何int类型的参数,anySet匹配任何set等等。
*/
@Test
public void argumentMatcherTest2(){
Map<Integer,String> map = mock(Map.class);
when(map.put(anyInt(),anyString())).thenReturn("hello");//anyString()替换成"hello"就会报错
map.put(1, "world");
verify(map).put(eq(1), eq("world")); //eq("world")替换成"world"也会报错
}
@Test
public void verifyInvocate(){
List<String> mockedList = mock(List.class);
//using mock
mockedList.add("once");
mockedList.add("twice");
mockedList.add("twice");
mockedList.add("three times");
mockedList.add("three times");
mockedList.add("three times");
/**
* 基本的验证方法
* verify方法验证mock对象是否有没有调用mockedList.add("once")方法
* 不关心其是否有返回值,如果没有调用测试失败。
*/
verify(mockedList).add("once");
// verify(T mock, VerificationMode mode) mode表示调用次数 默认是times(1)
verify(mockedList, times(1)).add("once");//默认调用一次,times(1)可以省略
verify(mockedList, times(2)).add("twice");
verify(mockedList, times(3)).add("three times");
//never()等同于time(0),一次也没有调用
verify(mockedList, times(0)).add("never happened");
//atLeastOnece/atLeast()/atMost() atLeastOnece:至少被调用过一次
verify(mockedList, atLeastOnce()).add("three times");
verify(mockedList, atLeast(2)).add("twice");
// 最多被调用几次
verify(mockedList, atMost(5)).add("three times");
// 验证方法能够在指定的100毫秒内执行完成
verify(mockedList, timeout(100)).add("once");
// 在超时验证的同时可进行调用次数验证
verify(mockedList, timeout(100).times(1)).add("twice");
// 在指定的时间内完成执行次数
verify(mockedList, timeout(100).times(2)).add("three times");
// 在指定的时间内至少执行2次
verify(mockedList, timeout(100).atLeast(2)).add("three times");
}
@Test
public void verifyTest() {
List<String> mock = mock(List.class);
List<String> mock2 = mock(List.class);
when(mock.get(0)).thenReturn("helllo");
mock.get(0);
mock.get(1);
mock.get(2);
mock2.get(0);
verify(mock).get(2);
verify(mock, never()).get(3);
// 用于验证传入的mock对象是否存在没有验证过的调用方法。建议该方法不要频繁使用
verifyNoMoreInteractions(mock);
// 和verifyNoMoreInteractions一样,验证mock2没有验证过任何方法
verifyZeroInteractions(mock2);
}
@Test
public void inorderTest() {
List<String> firstMock = mock(List.class);
List<String> secondMock = mock(List.class);
firstMock.add("was called first");
firstMock.add("was called first");
secondMock.add("was called second");
secondMock.add("was called third");
InOrder inOrder = inOrder(firstMock, secondMock);
// 下面两个验证必须按照上面上面方法执行的顺序验证, 否则报错
inOrder.verify(firstMock, times(2)).add("was called first");
inOrder.verify(secondMock).add("was called second");
// inOrder.verify(secondMock).add("was called third");
// 只验证创建order时提供的mock对象
inOrder.verifyNoMoreInteractions();
}
@Test
public void answerTest() {
List<String> mock3 = mock(List.class);
// 第一种写法
when(mock3.get(4)).thenAnswer(new CustomAnswer());
// 第二种写法
doAnswer(new CustomAnswer()).when(mock3.get(4));
//doAnswer(new CustomAnswer()).when(mock3).clear();
System.out.println(mock3.get(4));
}
@Test
public void argumentCaptorTest() {
List mock = mock(List.class);
List mock2 = mock(List.class);
mock.add("John");
mock2.add("Brain");
mock2.add("Jim");
ArgumentCaptor argument = ArgumentCaptor.forClass(String.class);
// argument.capture() 捕获方法参数
// 在verify方法的参数中调用argument.capture()来捕获输入的参数,之后argument变量中就保存了参数值。
verify(mock).add(argument.capture());
// argument.getValue() 获取方法参数值,如果方法进行了多次调用,它将返回最后一个参数值
assertEquals("John", argument.getValue());
verify(mock2, times(2)).add(argument.capture());
assertEquals("Jim", argument.getValue());
// 这里不正确。 argument中存了三个值
assertArrayEquals(new Object[] {"Brain", "Jim"}, argument.getAllValues().toArray());
}
// 当实际返回null可能抛出空指针时返回SmartNulls。String返回"" int返回0等
@Test
public void returnsSmartNullsTest() {
List mock = mock(List.class, RETURNS_SMART_NULLS);
System.out.println(mock.get(0));
System.out.println(mock.toArray().length);
}
/**
* spy--对象的监视
* mock对象只能调用stubbed方法,调用不了真实的方法。但 可以监视一个真实的对象,这时对它进行方法调用时它将调用真实的方法。
* 注意: 被监视的对象慎用when
*/
@Test
public void spyTest() {
List list = new LinkedList();
List spy = spy(list);
// 下面一句会报IndexOutOfBoundsException 因为是调真实对象的方法
// when(spy.get(0)).thenReturn("foo");
doReturn(100).when(spy).size();
spy.add("one");
spy.add("two");
System.out.println(spy.get(0));
System.out.println(spy.size());
verify(spy).add("one");
verify(spy).add("two");
}
}