mockito学习笔记

2017-12-21  本文已影响235人  crossroads

前言

根据中文版mockito英文版mockito的教程学习笔记。
这里只有基础的一些,更深的目前没有用到,也就没写了,大家直接进链接看吧!

一、验证某些行为

一旦mock对象被创建了,mock对象会记住所有的交互。

    @Test
    @DisplayName("验证某些行为")
    void verifyBehavior() {
        //创建mockito对象
        List mockedList = mock(List.class);
        mockedList.add("one");
        mockedList.clear();
        //验证行为
        verify(mockedList).add("one");
        verify(mockedList).clear();
    }

二、测试桩

 @Test
 void stubbing() {
        List mock = mock(ArrayList.class); //默认情况下,所有的函数都有返回值。mock函数默认返回的是null,一个空的集合或者一个被对象类型包装的内置类型,例如0、false对应的对象类型为Integer、Boolean
        System.out.println(mock + "--" + mock.size()); //输出Mock for ArrayList, hashCode: 480490520--0
        mock.add(0, "win");
        when(mock.get(0)).thenReturn("first"); //一旦测试桩函数被调用,该函数将会一致返回固定的值
        System.out.println(mock.get(0)); //输出first
        when(mock.get(0)).thenReturn("first change");
        when(mock.get(1)).thenReturn(new IndexOutOfBoundsException());
        System.out.println(mock.get(0)); //输出second
        System.out.println(mock.get(1)); //输出java.lang.IndexOutOfBoundsException
        //get(2) 没有打桩
        System.out.println(mock.get(2)); //输出null
 }

三、参数匹配器

    @Test
    void argumentMatchers() {
        List mock = mock(ArrayList.class);
        when(mock.get(anyInt())).thenReturn("element");
        System.out.println(mock.get(10086));//输出element
    }

四、验证函数的调用次数

    @Test
    void verifyExactNumber() {
        List mockedList = mock(List.class);
        mockedList.add("once");
        mockedList.add("twice");
        mockedList.add("twice");
        verify(mockedList, times(1)).add("once"); //执行了一次
        verify(mockedList, times(2)).add("twice");//执行了两次
        verify(mockedList, never()).add("never");
        verify(mockedList,atLeastOnce()).add("twice");
        verify(mockedList,atLeast(2)).add("twice");
        verify(mockedList,atMost(2)).add("twice");
    }

五、抛出异常

    @Test
    void throwExceptions(){
        List mockedList = mock(List.class);
//        doThrow(new RuntimeException()).when(mockedList).clear();
        doThrow(new RuntimeException()).when(mockedList).contains(anyInt());
//        mockedList.clear(); //抛出java.lang.RuntimeException异常
        mockedList.contains(1); //抛出java.lang.RuntimeException异常
    }

六、确保交互操作不会执行在mock对象上

    @Test
    void makeSureInteractionsNeverHappened(){
        List mockedList = mock(List.class);
        List mockedList2 = mock(List.class);
        mockedList.addAll(mockedList2);
        verifyZeroInteractions(mockedList,mockedList2);//抛出org.mockito.exceptions.verification.NoInteractionsWanted异常
    }

七、验证执行顺序

 @Test
    void verificationInOrder(){
        List mockedList = mock(List.class);
        mockedList.add("first");
        mockedList.add("second");
        InOrder inOrder = inOrder(mockedList);
        inOrder.verify(mockedList).add("first");
        inOrder.verify(mockedList).add("second");

        List firstMockedList = mock(List.class);
        List secondMockedList = mock(List.class);
        firstMockedList.add("first");
        secondMockedList.add("first");
        InOrder multipleOrder = inOrder(firstMockedList, secondMockedList);
        multipleOrder.verify(firstMockedList).add("first");
        multipleOrder.verify(secondMockedList).add("first");
        verifyZeroInteractions(mockedList,firstMockedList,secondMockedList);
    }

八、查找冗余的调用

即验证传入的这些mock对象是否存在没有验证过的调用方法

    @Test
    void findRedundantInvocations() {
        List mockedList = mock(List.class);
        mockedList.add("one");
        verifyNoMoreInteractions(mockedList);//抛出org.mockito.exceptions.verification.NoInteractionsWanted异常
    }

verifyNoMoreInteractions()在交互测试套件中只是一个便利的验证,它的作用是当你需要验证是否存在冗余调用时。滥用它将导致测试代码的可维护性降低,所以不建议过于频繁的在每个测试方法中都使用。

九、简化mock对象的创建

    @Mock
    private ArrayList mockedList;
    @BeforeEach
    void setUp() {
        MockitoAnnotations.initMocks(this);
    }
    @Test
    void verifyBehavior() {
        mockedList.add("one");
        verify(mockedList).add("one");
    }

十、为连续的调用做测试桩

    @Test
    void stubbingConsecutiveCalls(){
        when(mockedList.get(0)).thenReturn("first").thenReturn("second");
        //也可以这样写
        // when(mockedList.get(0)).thenReturn("first","second");
        System.out.println(mockedList.get(0)); //输出first
        System.out.println(mockedList.get(0)); //输出second
    }

等价于

doReturn("first","second").when(mockedList).get(0);
System.out.println(mockedList.get(0)); //输出first
System.out.println(mockedList.get(0)); //输出second

这两种方式还是有区别的,我们在十一条中讲。

十一、局部mocks(1.8.0+支持)

    @Test
    void realPartialMocks(){
        when(mockedList.get(10)).thenCallRealMethod(); //将会调用真实的方法
        System.out.println(mockedList.get(10));
    }

在一些罕见的情况下部分测试才会是易用的:处理不能轻易修改的代码(第三方接口,临时重构的遗留代码等等)。然而,为了新的,测试驱动和架构优秀的代码,我是不会使用部分测试的。

十二、重置mocks对象

        reset(mockedList);

十三、小技巧~模板代码

val eventLogicStub: EventLogic
    get() = mock(EventLogic::class.java).apply {

        doReturn(Observable.just(events))
                .`when`(this)
                .getEventsXX(anyString(), anyBoolean())

      doReturn(Single.just(events))
                .`when`(this)
                .getEventXX(anyString(), anyBoolean())

        doReturn(Single.just(files))
                .`when`(this)
                .getFilesXXX(anyString(), anyBoolean())

       doReturn(Maybe.just(files))
                .`when`(this)
                .getFileXX(anyString(), anyBoolean())
......
    }

这样子一个个重复劳动该怎么省去呢?用代码模板,我的是这样的:
输入dro,就可以得到如下的代码↓


自定义快捷输入

如何做?如何写?如下图


模板代码

如果你看到如下这样的提示,点击define,选择所在的组,例如我的是kotlin
文件,就选择kotlin啦


参考网址

Android Studio 模板用法与自定义模板

上一篇下一篇

猜你喜欢

热点阅读