OkHttp3IdlingResource

简介

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 首先是肯定要implementsIdlingResource,所以就有如下三个接口了:

@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.

你可能感兴趣的:(OkHttp3IdlingResource)