Android单元测试-Mockito的使用
来源:互联网 发布:6人游定制旅行怎样知乎 编辑:程序博客网 时间:2024/05/17 03:01
申明依赖
testCompile"junit:junit:$rootProject.ext.junitVersion"testCompile"org.mockito:mockitoall:$rootProject.ext.mockitoVersion"
测试代码写在test 文件夹下
如果是这样:androidTestCompile"junit:junit:$rootProject.ext.junitVersion"androidTestCompile "org.mockito:mockito-core:$rootProject.ext.mockitoVersion"
测试代码写在androidTest文件夹下junitVersion = '4.12'mockitoVersion = '1.10.19'
创建Mockito
@Beforepublic void setUp() { MockitoAnnotations.initMocks(this); }
验证行为
method:
- Mockito.verify() :验证Mock对象的方法是否被调用。
- Mockito.times() :调用Mock对象的方法次数。
- Mockito.atMost(count) , Mockito.atLeast(count) , Mockito.never() :最多次数,最少次数,永远调用。
- Mockito.anyInt() , Mockito.anyLong() , Mockito.anyDouble()等等 : 参数设置-任意的Int类型,任意的Long类型。。。等。
//Let's import Mockito statically so that the code looks clearer import static org.mockito.Mockito.*; //mock creation List mockedList = mock(List.class); //using mock object mockedList.add("one"); mockedList.clear(); //verification verify(mockedList).add("one"); verify(mockedList).clear();
解读:
1.mock一个List的到测试对象
2.verify(Object)调用add方法
3.可以验证是否调用add方法是否被调用
下面的描述来自 Mock以及Mockito的使用
Mockito.verify(mockUserManager).performLogin("xiaochuang", "xiaochuang password");
验证mockUserManager的performLogin()得到了调用,同时参数是“xiaochuang”和"xiaochuang password"。其实更准确的说法是,这行代码验证的是,mockUserManager的performLogin()方法得到了一次调用。因为这行代码其实是:Mockito.verify(mockUserManager,Mockito.times(1)).performLogin("xiaochuang","xiaochuang password");
的简写,或者说重载方法,注意其中的Mockito.times(1)
。因此,如果你想验证一个对象的某个方法得到了多次调用,只需要将次数传给Mockito.times()
就好了。Mockito.verify(mockUserManager,Mockito.times(3)).performLogin(...); //验证mockUserManager的performLogin得到了三次调用。
对于调用次数的验证,除了可以验证固定的多少次,还可以验证最多,最少从来没有等等,方法分别是:atMost(count), atLeast(count), never()等等,都是Mockito的静态方法,其实大部分时候我们会static import Mockito这个类的所有静态方法,这样就不用每次加上Mockito.前缀了。本文下面我也按照这个规则。(其实我早就想说这句话啦,只是一直没找到好的时机[喜极而泣])
很多时候你并不关心被调用方法的参数具体是什么,或者是你也不知道,你只关心这个方法得到调用了就行。这种情况下,Mockito提供了一系列的any方法,来表示任何的参数都行:
Mockito.verify(mockUserManager).performLogin(Mockito.anyString(),Mockito.anyString());
anyString()表示任何一个字符串都可以。null?也可以的!类似anyString,还有anyInt, anyLong, anyDouble等等。anyObject表示任何对象,any(clazz)表示任何属于clazz的对象。在写这篇文章的时候,我刚刚发现,还有非常有意思也非常人性化的anyCollection,anyCollectionOf(clazz), anyList(Map, set), anyListOf(clazz)等等。
指定mock对象的某些方法的行为
LinkedList mockedList = mock(LinkedList.class); when(mockedList.get(0)).thenReturn("first"); when(mockedList.get(1)).thenThrow(new RuntimeException());
解读:
- 默认情况下,所有方法都会返回值,一个 mock 将返回要么 null,一个原始/基本类型的包装值或适当的空集。例如,对于一个 int/Integer 就是 0,而对于 boolean/Boolean 就是 false。
- 默认值 可以被覆盖。
- 一旦 指定值,该方法将始终返回指定值,无论它有多少次被调用。
如 when(mockedList.get(0)).thenReturn("first"); 调用mockedList.get(0)的时候,因为指定了返回值 thenReturn("first"); 所以返回的值就是指定值 first
怎么样指定一个方法执行特定的动作
下文均摘自 Mock以及Mockito的使用
- doNothing() doAnswer() doThrow()
这个功能一般是用在目标的方法是void类型的时候。现在假设我们的LoginPresenter的login()方法是这样的:
public void loginCallbackVersion(String username, String password) { if (username == null || username.length() == 0) return; //假设我们对密码强度有一定要求,使用一个专门的validator来验证密码的有效性 if (mPasswordValidator.verifyPassword(password)) return; //login的结果将通过callback传递回来。 mUserManager.performLogin(username, password, new NetworkCallback() { @Override public void onSuccess(Object data) { //update view with data } @Override public void onFailure(int code, String msg) { //show error msg } });}
在这里,我们想进一步测试传给mUserManager.performLogin的NetworkCallback里面的代码,验证view得到了更新等等。在测试环境下,我们并不想依赖mUserManager.performLogin的真实逻辑,而是让mUserManager直接调用传入的NetworkCallback的onSuccess或onFailure方法。这种指定mock对象执行特定的动作的写法如下:Mockito.doAnswer(desiredAnswer).when(mockObject).targetMethod(args);
传给doAnswer()的是一个Answer对象,我们想要执行什么样的动作,就在这里面实现。结合上面的例子解释:
Mockito.doAnswer(new Answer() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { //这里可以获得传给performLogin的参数 Object[] arguments = invocation.getArguments(); //callback是第三个参数 NetworkCallback callback = (NetworkCallback) arguments[2]; callback.onFailure(500, "Server error"); return 500; }}).when(mockUserManager).performLogin(anyString(), anyString(),any(NetworkCallback.class));
这里,当调用mockUserManager的performLogin方法时,会执行answer里面的代码,我们上面的例子是直接调用传入的callback的onFailure方法,同时传给onFailure方法500和"Server error"。
当然,使用Mockito.doAnswer()需要创建一个Answer对象,这有点麻烦,代码看起来也繁琐,如果想简单的指定目标方法“什么都不做”,那么可以使用Mockito.doNothing()。如果想指定目标方法“抛出一个异常”,那么可以使用Mockito.doThrow(desiredException)。如果你想让目标方法调用真实的逻辑,可以使用Mockito.doCallRealMethod()。(什么??? 默认不是会这样吗??? No! )
Spy
Mock对象只能调用stubbed方法,调用不了它真实的方法。但Mockito可以监视一个真实的对象,这时对它进行方法调用时它将调用真实的方法,同时也可以stubbing这个对象的方法让它返回我们的期望值。另外不论是否是真实的方法调用都可以进行verify验证。和创建mock对象一样,对于final类、匿名类和Java的基本类型是无法进行spy的。
监视对象
监视一个对象需要调用spy(T object)方法,如:List spy = spy(new LinkedList());那么spy变量就在监视LinkedList实例。
被监视对象的Stubbing
stubbing被监视对象的方法时要慎用when(Object),如:
List spy = spy(new LinkedList()); //Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty) when(spy.get(0)).thenReturn("foo"); //You have to use doReturn() for stubbing doReturn("foo").when(spy).get(0);
当调用when(spy.get(0)).thenReturn("foo")时,会调用真实对象的get(0),由于list是空的所以会抛出IndexOutOfBoundsException异常,用doReturn可以避免这种情况的发生,因为它不会去调用get(0)方法。
下面是官方文档给出的例子:
@Test public void spyTest2() { List list = new LinkedList(); List spy = spy(list); //optionally, you can stub out some methods: when(spy.size()).thenReturn(100); //using the spy calls real methods spy.add("one"); spy.add("two"); //prints "one" - the first element of a list System.out.println(spy.get(0)); //size() method was stubbed - 100 is printed System.out.println(spy.size()); //optionally, you can verify verify(spy).add("one"); verify(spy).add("two"); }
作者:joxHero
链接:http://www.jianshu.com/p/6334d1e2babf
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
- Android单元测试-Mockito的使用
- Android单元测试(二):Mockito框架的使用
- Android 单元测试 Mockito使用详解
- Android单元测试(四):Mock以及Mockito的使用
- Android本地单元测试-mockito的使用(Kotlin版本)
- 使用Mockito和Roboletric进行Android单元测试
- 二.Android单元测试 Mockito的更多用法
- 一.Android单元测试 Mockito的简单用法
- Mockito单元测试-注解的详细使用
- 使用Eclipse写Mockito单元测试的问题
- Android单元测试-Mockito
- 使用Mockito进行单元测试
- Android-使用Mockito、Robolectric和RxJava及Retrofit进行单元测试
- 使用Mockito进行java单元测试
- 使用Mockito进行Java单元测试
- Mockito java单元测试框架使用
- Android中Mock以及Mockito的使用
- 单元测试:Mockito
- mysql的事务
- Spark调优: 基础篇
- iOS 精美过度动画源码、网络音乐播放器源码、雷达图源码等
- 百度api获取用户位置
- iOS中JS与原生OC互相调用之问题总结一
- Android单元测试-Mockito的使用
- JavaScript Java
- 01——mock
- 笔记--jstl标签
- mysql_connect(): Headers and client library minor version mismatch. Headers:
- Ubuntu安装faster-rcnn编译caffe版本不兼容问题
- FastDFS与Springboot集成
- 浅析WPF中MVVM模式下命令与委托的关系
- ABAP创建透明表