使用Robolectric测试okHttp请求 - 回调函数

5

我有一个需要测试的函数,它在okHttp回调中运行。我尝试使用Robolectrics进行测试,但是回调从未执行。我推测这是因为测试在请求后立即移动而没有等待okHttp返回。到目前为止,我已经尝试了以下方法:

    ShadowLooper.pauseMainLooper();
    Robolectric.flushBackgroundScheduler();
    ShadowLooper.unPauseMainLooper();

但是那并没有起作用。有什么建议吗?
编辑:
以下是我的代码示例:
ApiClient.sendSomeDataToServer(data, callback);

ApiClient是一个包含okHttp客户端的辅助类。sendSomeDataToServer API调用看起来像这样:

public static void sendSomeDataToServer(MyObject data, Callback callback){
    final Request request = new Request.Builder()
            .url(API_SOME_URL)
            .post(RequestBody.create(JSON, myObject.getAsJson().toString()))
            .build();
    sHttpClient.newCall(request).enqueue(callback);
}

这里的sHttpClient是一个已初始化的OkHttpClient。

我可以通过在测试代码中强制使用Thread.sleep(5000)并提供自定义回调来测试上述执行。我要测试的代码位于回调函数内部。有什么建议吗?我真的不想改动主要代码以适应测试框架 - 应该反过来。


你使用任何依赖注入吗? - Eugen Martynov
2个回答

7
假设你有以下代码。接口:
@GET("/user/{id}/photo")  
void listUsers(@Path("id") int id, Callback<Photo> cb);

实现:

public void fetchData() {
    RestAdapter restAdapter = new RestAdapter.Builder()
                .setServer("baseURL")     
                .build();
    ClientInterface service = restAdapter.create(ClientInterface.class);

    Callback<Photo> callback = new Callback<Photo>() {
        @Override
        public void success(Photo o, Response response) {

        }

        @Override
        public void failure(RetrofitError retrofitError) {

        }
    };
    service.listUsers(435, callback);
}

首先,您需要将service实例化更改为service注入(作为参数或字段)。我将使用参数进行操作:

public void fetchData(ClientInterface clients) {
}

接下来的内容相当琐碎:

@Test
public void checkThatServiceSuccessIsProcessed() {
    ClientInterface mockedClients = mock(ClientInterface.class);

    activity.fetchData(mockedClients);

    // get callback
    ArgumentCaptor<Callback<Photo>> captor = (ArgumentCaptor<Callback<Photo>>)ArgumentCaptor.forClass(Callback.class);
    verify(mockedInterface).listUsers(anything(), captor.capture());
    Callback<Photo> passedCallback = captor.value();
    // run callback
    callback.success(...);
    // check your conditions
}

用于模拟和验证的库是Mockito

由于泛型的存在,实例化captor时会有一个警告,但如果您使用@Captor注释而不是手动创建captor,则可以解决这个问题。

参数注入并不完美,尤其是对于活动的情况。这只是为了简化示例而已。考虑使用库或不使用库进行适当的注入。我建议您尝试使用Dagger进行注入。


当然可以。您可以编写自己的ClientInterface实现,从中捕获方法的回调并在测试中使用它。但是,如果Mockito已经为您提供了这些类,为什么要编写自己的类呢? - Eugen Martynov
我正在使用一台真实的服务器。 - vkislicins
这也是一个选择。我没有问话题发起者是否进行了单元测试。你的测试存在以下问题:1)速度较慢;2)当它失败时,你需要猜测是代码还是服务器的原因。 - Eugen Martynov
不幸的是,这并没有真正帮助我 - 我没有使用Retrofit,只是用okHttp,并且我不想改变我的代码来适应测试 - 这感觉不对。 - vkislicins
以答案为例。主要信息是你应该分离依赖项的创建和使用时刻。 - Eugen Martynov
显示剩余3条评论

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接