单元测试 笔记

单元测试 笔记

标签(空格分隔): TestNg mockito


学习链接
Mockito官方文档
极客学院
TestNg
Mockito中文教程

Mockito 使用情景

我们往往会遇到要测试的类有很多依赖,这些依赖的类/对象/资源又有别的依赖,从而形成一个大的依赖树,要在单元测试的环境中完整地构建这样的依赖,是一件很困难的事情。

基本使用

    @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()

    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().doReturndoReturn().when()的区别

  • doReturn().when()不会真的去调用该方法
  • when().doReturn()在监测对象是完全mock对象的时候不会调用方法(因为mock就是一个假对象),而当对象是spy的时候会真的去调用该方法
  • 当调用方法返回值是空的时候,只能用doReturn().when().method()

验证异常

代码验证

    @Rule
    public ExpectedException expectedEx = ExpectedException.none(); 
    //...
    expectedEx.expect(CannotUploadTemplateException.class);
    expectedEx.expectMessage("Template Rejected"); 
    expectedEx.expect(CannotUploadTemplateException.class);
    expectedEx.expectMessage("Template Rejected"); 

使用注释来验证异常

    @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对象

    @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

     @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());
    }

连续调用

    @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

猜你喜欢

转载自blog.csdn.net/xfzero/article/details/79098996