单元测试 笔记 学习链接Mockito官方文档 极客学院 TestNg Mockito中文教程
Mockito 使用情景 我们往往会遇到要测试的类有很多依赖,这些依赖的类/对象/资源又有别的依赖,从而形成一个大的依赖树,要在单元测试的环境中完整地构建这样的依赖,是一件很困难的事情。
基本使用 1 2 3 4 5 6 7 8 9 10 @Test public void test() { ObjectB objectB = mock(ObjectB.class); ObjectA objectA = new ObjectA(); objectA.setPwString("testString"); when(objectB.getObjectA()).thenReturn(objectA); ObjectA actucalA = objectB.getObjectA(); assertEquals(objectA, actucalA); }
注意使用注释快速Mock的时候需要MockitoAnnotations.initMocks(this);
参考2.5
参数匹配 在匹配方法的参数时候可以写准确值也可以使用any()
1 2 3 4 5 6 7 when(templateDAO.findAll(any(TemplateSpecification.class))).thenThrow(new DataAccessException("query template failed") { private static final long serialVersionUID = -6784264998739312988L; }); when(templateDAO.findAll(any(TemplateSpecification.class))).thenThrow(new DataAccessException("query template failed") { });
这里需要注意的是一旦参数使用了一个matcher,那么后面的参数都必须matcher
可以自己自定义参数匹配
doReturn().when()和when().doReturn()区别 这里需要注意一下when().doReturn
和doReturn().when()
的区别
doReturn().when()不会真的去调用该方法
when().doReturn()在监测对象是完全mock对象的时候不会调用方法(因为mock就是一个假对象),而当对象是spy的时候会真的去调用该方法
当调用方法返回值是空的时候,只能用doReturn().when().method()
验证异常 代码验证 1 2 3 4 5 6 7 @Rule public ExpectedException expectedEx = ExpectedException.none(); //... expectedEx.expect(CannotUploadTemplateException.class); expectedEx.expectMessage("Template Rejected"); expectedEx.expect(CannotUploadTemplateException.class); expectedEx.expectMessage("Template Rejected");
使用注释来验证异常 1 2 3 4 5 6 7 @Test(expected = RuntimeException.class) public void doThrow_when () { List list = mock(List.class); doThrow(new RuntimeException ()).when(list).add(1 ); list.add(1 ); }
Spy检测对象 spy是一个可以检测实际对象的技术,能够监测方法并设置对象行为,这里就需要注意之前所说的 doReturn().when()
和when().doReturn()
的区别,理解起来就是一种可实可虚的半mock对象
1 2 3 4 5 6 7 8 9 10 11 12 13 @Test public void test() { ObjectB objectB = spy(new ObjectB()); ObjectA objectA = new ObjectA(); objectA.setPwString("testString"); when(objectB.getObjectA()).thenReturn(objectA); ObjectA actucalA = objectB.getObjectA(); assertEquals(objectA, actucalA); //这里getValue()会调用实际的方法,返回值是"hello world" assertEquals("hello world", objectB.getValue()); }
重置Mock 1 2 3 4 5 6 7 8 9 10 @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()); }
连续调用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 @Test(expected = RuntimeException.class) public void consecutive_calls(){ //模拟连续调用返回期望值,如果分开,则只有最后一个有效 when(mockList.get(0)).thenReturn(0); when(mockList.get(0)).thenReturn(1); when(mockList.get(0)).thenReturn(2); when(mockList.get(1)).thenReturn(0).thenReturn(1).thenThrow(new RuntimeException()); assertEquals(2,mockList.get(0)); assertEquals(2,mockList.get(0)); assertEquals(0,mockList.get(1)); assertEquals(1,mockList.get(1)); //第三次或更多调用都会抛出异常 mockList.get(1); }
验证执行顺序 详情参考2.16
确保模拟对象上无互动发生 详情参考2.17
找出冗余的互动(即未被验证到的) 详情参考2.18