Mockito初探(三)——特别的Mock

Mockito 除了常用的 stub 和 verify 功能外,还可以完成一些特别的 stub 操作以及使用 spy 进行特别的 mock。

Stub 返回不同值

@Mock
private List mockedList;

@Before
public void before() {
    MockitoAnnotations.initMocks(this);
}

@Test
public void stubMultipleResult() {
    when(mockedList.get(anyInt())).thenReturn("first get").thenReturn("more than once get");

    System.out.println(mockedList.get(0));
    System.out.println(mockedList.get(0));
    System.out.println(mockedList.get(0));
}

可以通过上面的方式使第一次调用的时候返回第一个 thenReturn 的值,第二次调用返回第二个 thenReturn 的值,这种返回值方式只能顺序调用返回,当返回值进行到最后一个 thenReturn 时,无论再进行多少次调用都只会返回最后一个 thenReturn 的结果,当然也可以使用 thenThrowthenAnswer 等方法替换 thenReturn。当然,实现同样功能也有简洁写法。

when(mockedList.remove(anyInt())).thenReturn("first remove", "twice remove", "more than twice remove");

System.out.println(mockedList.remove(0));
System.out.println(mockedList.remove(0));
System.out.println(mockedList.remove(0));
System.out.println(mockedList.remove(0));

将返回值依次作为 thenReturn 方法的参数传入也可以实现同样效果。

需要注意的是,不能将两次 thenReturn 分开写,如果分开写,后面一个 thenReutrn 会覆盖前一个 thenReturn 的结果。

when(mockedList.remove(anyInt())).thenReturn("first remove");
when(mockedList.remove(anyInt())).thenReturn("twice remove");

Stub 自定义返回

使用 stub 时可以返回一些简单的结果,如同之前提到的一些 stub 的例子,如果我们想要根据调用方法的参数等进行逻辑处理,再生成相应结果返回呢?这种情况可以使用 thenAnswer 方法,加上自定义实现 Answeranswer 方法解决。

@Test
public void stubCallback() {
    when(mockedList.set(anyInt(), any())).thenAnswer(new Answer<Object>() {
        public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
            Object[] args = invocationOnMock.getArguments();
            Object mocked = invocationOnMock.getMock();
            return "arguments are: " + args;
        }
    });

    System.out.println(mockedList.set(1, "Answer callback"));
}

亦真亦假的 Spy

通过 spy 方法也可以生成一个 mock 对象,不过 spy 与 mock 相比的特别之处在于,如果被调用的 spy 对象的方法没有 stub,会直接调用真实对象的相应方法。

@Test
public void spyObject() {
    ArrayList<Integer> arrayList = new ArrayList<Integer>();
    ArrayList spyList = spy(arrayList);

    doReturn(100).when(spyList).size();

    System.out.println(spyList.size());

    spyList.add(0);
    spyList.add(1);

    System.out.println(spyList.size());
    System.out.println(spyList.toString());

    verify(spyList).add(0);
    verify(spyList).add(1);
}

当你只是需要 mock 部分方法,而又需要另外一些方法的真实调用时,使用 spy 再适宜不过。不过,需要注意的是,对 spy 对象进行 stub 时尽量使用 doReturn.when(spyObj).someMethod() 的方式,因为当使用 when(spyObj.someMethod()).thenReturn() 方式时 someMethod 相当于在 stub 之前被调用了一次,而 spy 对象调用未被 stub 的方法时,会直接调用原对象的相应方法,容易造成异常。

如下的例子中,spyList 在没有元素的情况下调用 get 方法就会造成下标越界的异常。

ArrayList<Integer> arrayList = new ArrayList<Integer>();
ArrayList spyList = spy(arrayList);

when(spyList.get(0)).thenReturn("call get");

总结

这章描述了多次调用 stub 方法返回不同结果和自定义 stub 方法响应逻辑,还有 spy 这种特别的 mock 方式以及使用这些功能时的一些注意事项。


本章节示例代码已经上传 GitHub,可点击跳转查看代码详情

转载于:https://www.jianshu.com/p/c40fa4720544

猜你喜欢

转载自blog.csdn.net/weixin_33729196/article/details/91195741