简介
OkHttp3IdlingResource是Jake Wharton大神为okhttp写的Espresso的IdlingResource,目前支持到OkHttp3.
使用方法比较简洁:
1、在test case 开始之前,注册根据OkHttpClient实例创建的IdlingResource
OkHttpClient client =//...
IdlingResource resource = OkHttp3IdlingResource.create( "OkHttp", client);
Espresso.registerIdlingResources(resource);
2、在test case结束后,注销IdlingResource
Espresso.unregisterIdlingResources(resource);
源码可以参见:https://github.com/JakeWharton/okhttp-idling-resource
剖析实现方式
OkHttp3IdlingResource 首先是肯定要implements
IdlingResource,所以就有如下三个接口了:
@Override
public String getName() {
return name;
}
@Override
public boolean isIdleNow() {
return dispatcher.runningCallsCount() == 0;
}
@Override
public void registerIdleTransitionCallback(ResourceCallback callback) {
this.callback = callback;
}
这三个接口的解释,请参考Espresso UI测试#IdlingResource
从这三个接口,目前也没有发现很高深的内容,那大神是怎么实现的呢?
我们要看上文使用方式里的create OkHttp3IdlingResource的方法了:
@CheckResult
@NonNull
@SuppressWarnings("ConstantConditions") // Extra guards as a library.
public static OkHttp3IdlingResource create(@NonNull String name, @NonNull OkHttpClient client) {
if (name == null) throw new NullPointerException("name == null");
if (client == null) throw new NullPointerException("client == null");
return new OkHttp3IdlingResource(name, client.dispatcher());
}
1、name 和 client 是不可以为null,如果是null,就抛exception
2、如果name 和 client都不是null,则创建OkHttp3IdlingResource
private OkHttp3IdlingResource(String name, Dispatcher dispatcher) {
this.name = name;
this.dispatcher = dispatcher;
dispatcher.setIdleCallback(new Runnable() {
@Override
public void run() {
ResourceCallback callback = OkHttp3IdlingResource.this.callback;
if (callback != null) {
callback.onTransitionToIdle();
}
}
});
}
1、当创建OkHttp3IdlingResource时,把HttpClient的dispatcher传递过来
2、调用dispatcher.setIdleCallback()
可是什么时候会触发这个Runnable内的run()函数呢?
我们去看OkHttp的Dispatcher这个类,show you the code:
private void finished(Deque calls, T call, boolean promoteCalls) {
int runningCallsCount;
Runnable idleCallback;
synchronized(this) {
if(!calls.remove(call)) {
throw new AssertionError("Call wasn\'t in-flight!");
}
if(promoteCalls) {
this.promoteCalls();
}
runningCallsCount = this.runningCallsCount();
idleCallback = this.idleCallback;
}
if(runningCallsCount == 0 && idleCallback != null) {
idleCallback.run();
}
}
可以看到是当runningCallsCount 为0 的时候,会触发。
正好结合官方文档里对setIdleCallback(Runnable idleCallback)这个函数的描述:
Set a callback to be invoked each time the dispatcher becomes idle (when the number of running calls returns to zero).
那么我们更肯定,当请求结束后,就是idle的状态了。
所以当我们在写UI测试时,对于使用OkHttp 进行网络请求的页面,就可以在test case 开始之前注册OkHttp3IdlingResource,在test case 结束后注销OkHttp3IdlingResource,而不用自己单独去实现IdlingResource这个接口了。
名词解释:
Dispatcher
Policy on when async requests are executed.
IdlingResource
Represents a resource of an application under test which can cause asynchronous background work to happen during test execution (e.g. an intent service that processes a button click). By default, Espresso synchronizes all view operations with the UI thread as well as AsyncTasks; however, it has no way of doing so with "hand-made" resources. In such cases, test authors can register the custom resource and {@link Espresso} will wait for the resource to become idle prior to executing a view operation.