Mockito的使用一

一、Mockito的引用
Gradle:

repositories { jcenter() }
dependencies { testCompile "org.mockito:mockito-core:1.+" }

Maven:

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>1.10.19</version>
</dependency>

二、使用
详情请参考:http://mockito.org/

1、验证某些行为:

//静态导入会使代码更简洁
 import static org.mockito.Mockito.*;

 //创建Mock对象
 List mockedList = mock(List.class);

 //使用 Mock对象
 mockedList.add("one");
 mockedList.clear();

 //验证
 verify(mockedList).add("one");
 verify(mockedList).clear();

其中 verify 方法 还有2个参数的方法:第二个参数可以传入 times(x),atLeastOne() 、never()、atMost(x)等,这些参数表示验证方法执行的次数。
如:

    {
     // 验证方法被调用次数
        LinkedList mockedList = mock(LinkedList.class);
        mockedList.add("one");

        mockedList.add("two");
        mockedList.add("two");

        mockedList.add("three");
        mockedList.add("three");
        mockedList.add("three");
    //验证 add("one")执行了1次
        verify(mockedList,times(2)).add("two");
        //验证 add("two")执行了2次
        verify(mockedList,times(3)).add("three");
    //验证 add("never")执行了3次
        verify(mockedList,never()).add("never");
        //验证 add("one")最少执行了1次
        verify(mockedList,atLeast(1)).add("one");
        //验证 add("three")最多执行了10次
        verify(mockedList,atMost(10)).add("three");

    }

如果第二个参数不写,相当于执行了 verify(mockedList,times(1))。

2、如何测试一些桩

//你可以mock具体的类型,不仅只是接口
 LinkedList mockedList = mock(LinkedList.class);

 //测试桩,在调用mockedList.get(0)时会返回 "first"
 when(mockedList.get(0)).thenReturn("first");
 //测试桩,在调用mockedList.get(1)时 会抛出RuntimeException异常
 when(mockedList.get(1)).thenThrow(new RuntimeException());

 //会打印出 "first"
 System.out.println(mockedList.get(0));

 //会抛出runtime exception
 System.out.println(mockedList.get(1));

 //mockedList.get(999)没有打桩 ,所以会打印出  "null" 
 System.out.println(mockedList.get(999));

3、参数匹配器

//使用内置的anyInt()参数匹配器,当调用get(整数值)时,都返回"element"
 when(mockedList.get(anyInt())).thenReturn("element");

 //使用自定义的参数匹配器,(在 isValid()函数中返回你自己的匹配器实现)
 when(mockedList.contains(argThat(isValid()))).thenReturn("element");

 //打印 "element"
 System.out.println(mockedList.get(999));

// 你也可以验证参数匹配器
 verify(mockedList).get(anyInt());

有一点需要注意,如果使用参数匹配器,那么所有的参数都因该有匹配器提供。
例如:

 //这个是正确的,因为 eq()也是一个参数匹配器
 verify(mock).someMethod(anyInt(), anyString(), eq("third argument"));

  //下面的代码是错误的,因为所有参数必须由匹配器提供,二参数"third argument"并非由参数//匹配器提供
   verify(mock).someMethod(anyInt(), anyString(), "third argument");

4、验证函数的执行次数

//using mock
 mockedList.add("once");

 mockedList.add("twice");
 mockedList.add("twice");

 mockedList.add("three times");
 mockedList.add("three times");
 mockedList.add("three times");

 //following two verifications work exactly the same - times(1) is used by default
 verify(mockedList).add("once");
 verify(mockedList, times(1)).add("once");

 //exact number of invocations verification
 verify(mockedList, times(2)).add("twice");
 verify(mockedList, times(3)).add("three times");

 //verification using never(). never() is an alias to times(0)
 verify(mockedList, never()).add("never happened");

 //verification using atLeast()/atMost()
 verify(mockedList, atLeastOnce()).add("three times");
 verify(mockedList, atLeast(2)).add("five times");
 verify(mockedList, atMost(5)).add("three times");

这些方法在将第一条的时候,已经提过了,这里就不在说明了。

5、为无返回值对象打桩抛出异常


    //当调用mockedList.clear()时,将抛出RuntimeException 异常
   doThrow(new RuntimeException()).when(mockedList).clear();

   //将抛出RuntimeException:
   mockedList.clear();

6、验证方法调用顺序:

 // A.当只有一个mock对象时
        List singleMock = mock(List.class);

        //使用单个mock对象
        singleMock.add("was added first");
        singleMock.add("was added second");

        //创建一个InOrder
        InOrder inOrder = Mockito.inOrder(singleMock);

      //确保add("was added first") 在add("was added second")之前
        inOrder.verify(singleMock).add("was added first");
        inOrder.verify(singleMock).add("was added second");

        // B. 多个Mock对象时
        List firstMock = mock(List.class);
        List secondMock = mock(List.class);

        //使用mock对象那个
        firstMock.add("was called first");
        secondMock.add("was called second");

        //create inOrder object passing any mocks that need to be verified in order
        InOrder inOrder = Mockito.inOrder(firstMock, secondMock);

        //确保firstMock.add("was called firs") 在 secondMock.add("was called second")之前
        inOrder.verify(firstMock).add("was called first");
        inOrder.verify(secondMock).add("was called second");

7、确保交互操作没有执行在Mock对象上

     List mockOne = mock(List.class);
        //使用Mock对新娘
        mockOne.add("one");

        //普通验证
        verify(mockOne).add("one");

        //验证 add("two") 没有执行过
        verify(mockOne, never()).add("two");

        List mockTwo = mock(List.class);
        List mockThree = mock(List.class);

        //验证mockTwo和mockThree 没有交互过
        verifyZeroInteractions(mockTwo, mockThree);

8、寻找多余的调用:

    List mockedList = mock(List.class);
        //常见mock对象
        mockedList.add("one");

        mockedList.add("two");
    //这里只验证了 add("one")没有验证add("two"),这将导致 //verifyNoMoreInteractions(mockedList);验证失败
        verify(mockedList).add("one");

        //这里将验证失败
        verifyNoMoreInteractions(mockedList);

9,简化Mock对象的创建
使用@Mock注解,它的好处在于:
1、最小化重复地创建代码
2、是测试类的代码可读性更高
3、是验证错误更易于阅读,因为字段名可以表示Mock对象

 public class ArticleManagerTest {

       @Mock private ArticleCalculator calculator;
       @Mock private ArticleDatabase database;
       @Mock private UserProvider userProvider;

       private ArticleManager manager;

注意,必须在调用 MockitoAnnotations.initMocks(testClass); 进行初始化。
例如可以在基类,或者当前类

 public class ArticleManagerTest extends SampleBaseTestCase { 

       @Mock private ArticleCalculator calculator;
       @Mock private ArticleDatabase database;
       @Mock private UserProvider userProvider;

       private ArticleManager manager;

       @Before public void setup() {
           manager = new ArticleManager(userProvider, database, calculator);
       }
   }

   public class SampleBaseTestCase {

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

10、为连续调用做测试桩

when(mock.someMethod("some arg"))
   .thenThrow(new RuntimeException())
   .thenReturn("foo");

 //第一次调用时: 抛出RuntimeException异常
 mock.someMethod("some arg");

 //第二次调用时,打印 "foo"
 System.out.println(mock.someMethod("some arg"));

 //后续的调用也是 输出"foo"
 System.out.println(mock.someMethod("some arg"));

还有一种简短版本:


 when(mock.someMethod("some arg"))
   .thenReturn("one", "two", "three");
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值