首页 > 代码库 > mockito框架
mockito框架
参考自
http://www.cnblogs.com/silence-hust/p/5017233.html
http://blog.csdn.net/sdyy321/article/details/38757135
首先创建一个maven工程
在pom文件中,存在如下依赖
<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-all</artifactId> <version>1.9.5</version> <scope>test</scope> </dependency> </dependencies>
1、验证行为是否发生
@Test public void mockedList(){ List mockedList = mock(List.class); mockedList.add("one"); mockedList.clear(); //验证add("one")和clear()行为是否发生 verify(mockedList).add("one"); verify(mockedList).clear(); }
2、验证返回值
@Test public void two(){ //模拟创建一个List对象 LinkedList mockLinkedList = mock(LinkedList.class); //打桩,当LinkedList调用get(0)方法时,第一次返回hello,第二次n次返回world when(mockLinkedList.get(0)).thenReturn("hello").thenReturn("world"); String result = mockLinkedList.get(0) + " " + mockLinkedList.get(0) + " " + mockLinkedList.get(0); //使用mock对象 System.out.println(mockLinkedList.get(0)); System.out.println(mockLinkedList.get(0)); System.out.println(mockLinkedList.get(0)); assertEquals("hello world world",result); }
这里注意所有的方法都会有返回值,如果没有设置返回值,那么就会返回null或者空集、适当的类型。 Stubbing可以被重写,也就是同一个参数方法可以放回不同的值,但是以最后一次设置的值为标准。一旦被 Stubbed,无论方法被调用多少次,都只会返回Stubbed value。最后一次最重要原则。
第一次运行打印 hello world world,这是第二次运行测试打印 world world world。
3、参数匹配
@Test public void with_arguments(){ Comparable comparable = mock(Comparable.class); //预设根据不同的参数返回不同的结果 when(comparable.compareTo("Test")).thenReturn(1); when(comparable.compareTo("Omg")).thenReturn(2); assertEquals(1, comparable.compareTo("Test")); assertEquals(2, comparable.compareTo("Omg")); //对于没有预设的情况会返回默认值 assertEquals(0, comparable.compareTo("Not stub")); }
除了匹配给定参数外,还可以使用参数匹配器 argumentMatchers,更加灵活
@Test public void argumentMatchersTest(){ List list = mock(List.class); //匹配任意int类型的值 when(list.get(anyInt())).thenReturn(1); assertEquals(1, list.get(1)); verify(list).get(anyInt()); assertEquals(1, list.get(999)); }
若方法中的某一个参数使用了matcher,则所有的参数都必须使用matcher:
@Test public void argumentMatchersTest2(){ Map map = mock(Map.class); //匹配任意参数 when(map.put(anyInt(),anyString())).thenReturn("world"); assertEquals("world", map.put(1,"hello")); //以下三种验证都可通过测试 verify(map).put(anyInt(),anyString()); verify(map).put(anyInt(),eq("hello")); verify(map).put(eq(1),eq("hello")); }
4、验证调用次数
@Test public void three(){ List mockedList = mock(List.class); mockedList.add(1); mockedList.add(2); mockedList.add(2); mockedList.add(3); mockedList.add(3); mockedList.add(3); //验证是否被调用一次,等效于下面的times(1),默认的,可以不写 verify(mockedList).add(1); verify(mockedList,times(1)).add(1); //验证是否被调用2次 verify(mockedList,times(2)).add(2); //验证是否被调用3次 verify(mockedList,times(3)).add(3); //验证是否从未被调用过 verify(mockedList,never()).add(4); //验证至少调用一次 verify(mockedList,atLeastOnce()).add(1); //验证至少调用2次 verify(mockedList,atLeast(2)).add(2); //验证至多调用3次 verify(mockedList,atMost(3)).add(3); }
5、模拟抛出异常
@Test(expected = IOException.class) public void when_thenThrow() throws IOException { OutputStream outputStream = mock(OutputStream.class); //预设当流关闭时抛出异常 ,因为close()返回类型为void,采用了doThrow 形式 doThrow(new IOException()).when(outputStream).close(); outputStream.close(); }
6、验证执行的顺序
@Test public void four(){ List firstList = mock(List.class); List secondList = mock(List.class); //using mocks firstList.add("was called first one mock"); firstList.add("was called second one mock"); secondList.add("was called third one mock"); secondList.add("was called fourth one mock"); //create inOrder object passing any mocks that need to be verified in order // InOrder indOrder = inOrder(firstList,secondList); InOrder indOrder = inOrder(secondList,firstList); //实际上两种顺序都通过测试了 indOrder.verify(firstList).add("was called first one mock"); indOrder.verify(firstList).add("was called second one mock"); indOrder.verify(secondList).add("was called third one mock"); indOrder.verify(secondList).add("was called fourth one mock"); }
7、验证零互动
@Test public void verify_interaction(){ List list = mock(List.class); List list2 = mock(List.class); List list3 = mock(List.class); list.add(1); verify(list).add(1); verify(list,never()).add(2); //验证零互动行为 verifyZeroInteractions(list2,list3); }
8、找出冗余的互动(即未被验证到的)
@Test public void find_redundant_interaction(){ List list = mock(List.class); list.add(1); list.add(2); verify(list,times(2)).add(anyInt()); //检查是否有未被验证的互动行为,因为add(1)和add(2)都会被上面的anyInt()验证到,所以下面的代码会通过 verifyNoMoreInteractions(list); //下面因为只验证了add(1),add(2)没有被验证,所以下面的代码会失败抛出异常 // List list2 = mock(List.class); // list2.add(1); // list2.add(2); //verify(list2).add(1); // verifyNoMoreInteractions(list2); }
9、使用注解来快速模拟
在上面的测试中我们在每个测试方法里都mock了一个List对象,为了避免重复的mock,是测试类更具有可读性,我们可以使用下面的注解方式来快速模拟对象:
- @Mock
- private List mockList;
@Mock private List mockList;
OK,我们再用注解的mock对象试试
- @Test
- public void shorthand(){
- mockList.add(1);
- verify(mockList).add(1);
- }
@Test public void shorthand(){ mockList.add(1); verify(mockList).add(1); }
运行这个测试类你会发现报错了,mock的对象为NULL,为此我们必须在基类中添加初始化mock的代码
- public class MockitoExample2 {
- @Mock
- private List mockList;
- public MockitoExample2(){
- MockitoAnnotations.initMocks(this);
- }
- @Test
- public void shorthand(){
- mockList.add(1);
- verify(mockList).add(1);
- }
- }
public class MockitoExample2 { @Mock private List mockList; public MockitoExample2(){ MockitoAnnotations.initMocks(this); } @Test public void shorthand(){ mockList.add(1); verify(mockList).add(1); }}
或者使用built-in runner:MockitoJUnitRunner
- @RunWith(MockitoJUnitRunner.class)
- public class MockitoExample2 {
- @Mock
- private List mockList;
- @Test
- public void shorthand(){
- mockList.add(1);
- verify(mockList).add(1);
- }
- }
@RunWith(MockitoJUnitRunner.class)public class MockitoExample2 { @Mock private List mockList; @Test public void shorthand(){ mockList.add(1); verify(mockList).add(1); }}
更多的注解还有@Captor,@Spy,@InjectMocks
mockito框架