PowerMock中对java接口进行测试


最近在对自己的项目写一些单元测试,选择了Powermock测试框架。

关于Powermock的使用网上有很多例子,这里不再介绍。但是开发代码中有很多地方使用了接口,搜了百度和谷歌都没有找到解决办法。

如题,这里介绍使用Powermock对接口进行测试的一种方法,特做记录。

待测试类和方法:这里以流行的OkHttpClient网络请求接口Callback为例

public class DownloadResource {

    public void downloadResource(String url){
        url += "/";
        Callback callback = new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                System.out.print("onFailure");
                //do something.
                doOtherMethod(false);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                System.out.print("onResponse");
                //do something.
                doOtherMethod(true);
            }
        };
        //从缓存中获取一个httpClient实例
        OkHttpClient httpClient = PafPluginCache.getInstance().getHttpClient();
        Request request = new Request.Builder().url(url).get().build();
        httpClient.newCall(request).enqueue(callback);
    }

    private void doOtherMethod(boolean b) {

    }
}

对应的测试类:

@RunWith(PowerMockRunner.class)
@PrepareForTest({DownloadResource.class, PafPluginCache.class})
public class DownloadResourceTest {

    @Test
    public void downloadResource() throws Exception {
        DownloadResource downloadResource = new DownloadResource();
        DownloadResource spy = spy(downloadResource);

        OkHttpClient okHttpClient = mock(OkHttpClient.class);
        PafPluginCache pafPluginCache = mock(PafPluginCache.class);
        mockStatic(PafPluginCache.class);
        when(PafPluginCache.getInstance()).thenReturn(pafPluginCache);
        when(pafPluginCache.getHttpClient()).thenReturn(okHttpClient);

        Request.Builder builder = mock(Request.Builder.class);
        when(builder.url(anyString())).thenReturn(builder);
        when(builder.get()).thenReturn(builder);

        Call call = mock(Call.class);
        when(okHttpClient.newCall(any(Request.class))).thenReturn(call);
        //替换mock的method的实现
        doAnswer(new Answer() {
            @Override
            public Object answer(InvocationOnMock invocation) throws Throwable {
                Object[] args = invocation.getArguments();
                System.out.print("proxy:" + invocation.getMock() + "\n");
                System.out.print("invoke(" + args[0] + /*", " + args[1] +*/ ")\n");
                Object o1 = args[0];
                if(o1 instanceof Callback){
                    Callback callback = (Callback) o1;
                    callback.onResponse(null, null);
                }
                return null;
            }
        }).when(call).enqueue(any(Callback.class));

        spy.downloadResource("http://www.abc.com");
        verifyPrivate(spy, times(1)).invoke("doOtherMethod", true);
    }
}

执行测试用例的结果:

简单总结一下原理,利用doAnswer方法获取到被测类中被测方法的入参,其中一个入参就是接口的实例DownloadResource$1@4a83a74a。然后我们就可以调用该接口实例的方法了。

 

另外,准备了一些对于Powermock的使用的个人经验,如有错误,欢迎指正。

  1. 通过mock(class)得到的mock对象,其所有非静态方法和域都是虚假的,如果要使用这些方法和域,需要先进行设置
  2. mockStatic(class)后,该类的所有静态方法和静态域都是虚假的,且需要加入到@PrepareForTest中,如果要使用这些方法和域,需要先进行设置
  3. android包下的所有类都自动被mock了,且无法通过callRealMethod方法使其真实,也包括org.json下的类。
  4. spy(object)中入参应为真实对象,和mock对象相反,其所有非静态方法和域都是真实的,可以对某个方法进行mock设置
  5. 使用verify系列方法可以验证mock对象和spy对象的方法执行次数
  6. 设置when系列方法进行mock条件时,可以传入具体值或者模糊值,但是同时传入具体值和模糊值时,具体值需要使用eq方法包装一下。调用方法时不可传入模糊值
  7. reset(mock)方法可以重置所有mock条件和verify系列方法的验证次数
  8. 调用私有方法可以使用Whitebox.invokeMethod系列方法
  9. suppress方法可以跳过任意一个方法,一般测试子类时,禁用父类方法。
  10. 使用inOrder方法来验证mock对象的调用顺序

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM