使用 Robolectric 测试 okHttp 请求 - 回调
Testing okHttp requests with Robolectric - callbacks
我有一个函数要测试,它在 okHttp 回调中运行。我正在尝试使用 Robolectrics 对其进行测试,但从未执行过回调。我认为这是因为测试在请求后继续进行,而不等待 okHttp 到 return。到目前为止我已经尝试过:
ShadowLooper.pauseMainLooper();
Robolectric.flushBackgroundScheduler();
ShadowLooper.unPauseMainLooper();
但这没有用。有什么建议吗?
编辑:
这是我的代码示例:
ApiClient.sendSomeDataToServer(data, callback);
其中 ApiClient 是一个包含 okHttp 客户端的助手 class。 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)
并提供自定义回调来测试上面的执行。我要测试的代码在回调中。有什么建议我可以测试吗?我真的不想更改主要代码以适应测试框架 - 应该反过来。
假设您有下一个代码。接口:
@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
注释而不是手动创建捕获器,它是可以修复的。
参数注入并不完美,尤其是对于活动的情况。这用于简化示例。考虑使用或不使用库进行正确注入。我鼓励您尝试 Dagger
注射
您可以使用 ArgumentCaptor(Mockito 的 class)。
参考:
http://www.mdswanson.com/blog/2013/12/16/reliable-android-http-testing-with-retrofit-and-mockito.html
我有一个函数要测试,它在 okHttp 回调中运行。我正在尝试使用 Robolectrics 对其进行测试,但从未执行过回调。我认为这是因为测试在请求后继续进行,而不等待 okHttp 到 return。到目前为止我已经尝试过:
ShadowLooper.pauseMainLooper();
Robolectric.flushBackgroundScheduler();
ShadowLooper.unPauseMainLooper();
但这没有用。有什么建议吗?
编辑:
这是我的代码示例:
ApiClient.sendSomeDataToServer(data, callback);
其中 ApiClient 是一个包含 okHttp 客户端的助手 class。 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)
并提供自定义回调来测试上面的执行。我要测试的代码在回调中。有什么建议我可以测试吗?我真的不想更改主要代码以适应测试框架 - 应该反过来。
假设您有下一个代码。接口:
@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
注释而不是手动创建捕获器,它是可以修复的。
参数注入并不完美,尤其是对于活动的情况。这用于简化示例。考虑使用或不使用库进行正确注入。我鼓励您尝试 Dagger
注射
您可以使用 ArgumentCaptor(Mockito 的 class)。 参考: http://www.mdswanson.com/blog/2013/12/16/reliable-android-http-testing-with-retrofit-and-mockito.html