Mock测试框架(Mockito为例)
在做单元测试的时候,有的时候用到的一些类,我们构造起来不是那么容易,比如HttpRequest,或者说某个Service依赖到了某个Dao,想构造service还得先构造dao,这些外部对象构造起来比较麻烦。 所以出现了Mock! 我们可以用 Mock 工具来模拟这些外部对象,来完成我们的单元测试。
实现Mock技术的优秀开源框架有很多,下面以Mockito为例,用几个简单例子来介绍Mock工具的基本使用:
1.Mockito的第一个示例
1 @Test 2 public void simpleTest(){ 3 4 //创建mock对象,参数可以是类,也可以是接口 5 List<String> list = Mockito.mock(List.class); 6 7 //设置方法的预期返回值 (如果list.get(0) 被调用 ,调用之后返回 helloworld) 8 //当然前提是要创建了Mock对象,如这里就是创建了跟 List相关的 Mock对象 9 //这里还看不出什么作用,因为Mock 还看不出来,List很容易就能创建 10 //假如是一个很复杂的对象,构造这样一个对象很有难度,使用Mock就很方便了,我们不用去一步一步填充它的属性去构造, 11 //只需要Mock 一下,就可以拿到这个对象,去测试它的方法,(当然,如果方法有参数我们是需要传递的,像get(0)) 12 Mockito.when(list.get(0)).thenReturn("helloworld"); 13 //list.get(0)的调用就会返回 helloworld 14 String result = list.get(0); 15 System.out.println(result); 16 17 //验证方法调用(是否调用了get(0)) 18 Mockito.verify(list).get(0); 19 20 Assert.assertEquals("helloworld", result); 21 }
1 @Test 2 public void testMockMethod() { 3 Class1Mocked obj=mock(Class1Mocked.class);① 4 5 when(obj.hello("z3")).thenReturn("hello l4");② 6 7 String actual=obj.hello("z3");③ 8 assertEquals("hello l4",actual); 9 10 verify(obj).hello("z3");④ 11 //verify(obj,times(1)).hello("z3"); //可以加参数验证次数 12 }
2.验证顺序
1 @Test 2 public void testMockMethodInOrder() { 3 Class1Mocked objOther = Mockito.mock(Class1Mocked.class); 4 Class1Mocked objCn = Mockito.mock(Class1Mocked.class); 5 6 Mockito.when(objOther.hello("z3")).thenReturn("hello l4"); 7 Mockito.when(objCn.hello("z3")).thenReturn("hello 张三"); 8 9 String other = objOther.hello("z3"); //这里决定了 objOther在先 10 Assert.assertEquals("hello l4", other); 11 String cn = objCn.hello("z3"); //这里决定了 objCn在后 12 Assert.assertEquals("hello 张三", cn); 13 14 InOrder inOrder = Mockito.inOrder(objOther, objCn); //此行并不决定顺序,下面的两行才开始验证顺序 15 inOrder.verify(objOther).hello("z3"); 16 inOrder.verify(objCn).hello("z3"); 17 }
3.非局部模拟
1 // 非局部模拟(只能通过When().thenReturn() 来指定函数的返回类型,但是是调用不了 模拟出来的的类的方法的) 2 @Test 3 public void testSkipExpect() { 4 Class1Mocked obj = Mockito.mock(Class1Mocked.class); 5 6 //如:正常如果hello方法被调用,应该返回z3,但这里返回的null ,说明该方法是没有被调用的 7 //因为我们模拟出来的是非局部变量 8 Assert.assertEquals(null, obj.hello("z3")); 9 //show方法也是一样,show方法如果执行应该打印一句话,但是obj并不能执行show方法 10 obj.show(); 11 12 Mockito.verify(obj).hello("z3"); 13 Mockito.verify(obj).show(); 14 }
4.局部模拟
1 //局部模拟--spy()方式 2 @Test 3 public void testSpy() { 4 Class1Mocked obj = Mockito.spy(new Class1Mocked()); 5 6 Mockito.doNothing().when(obj).show(); //有了这行,show方法被执行就不会有任何操作 7 8 Assert.assertEquals("z3",obj.hello("z3")); 9 obj.show(); 10 11 Mockito.verify(obj).hello("z3"); 12 Mockito.verify(obj).show(); 13 }
5.陷阱
1 //值得注意的陷阱 2 @Test 3 public void testSpy2() { 4 Class1Mocked obj = Mockito.spy(new Class1Mocked()); 5 //即使使用的是when thenReturn,但是仍然会执行方法里面的内容 6 Mockito.when(obj.hello("z3")).thenReturn("hello l4"); 7 8 Assert.assertEquals("hello l4",obj.hello("z3")); 9 10 Mockito.verify(obj).hello("z3"); 11 }
1 //如果既想使用局部模拟,又不想调用到方法里面的内容 2 @Test 3 public void testSpy3() { 4 Class1Mocked obj = Mockito.spy(new Class1Mocked()); 5 6 Mockito.doReturn("hello l4").when(obj).hello("z3"); 7 8 Assert.assertEquals("hello l4",obj.hello("z3")); 9 10 Mockito.verify(obj).hello("z3"); 11 }
参考博文:java的mock测试框架