在Espresso中监控Picasso for IdlingResource

时间:2015-09-25 09:53:43

标签: android picasso android-testing android-espresso

我希望能够将Espresso监视Picasso作为IdlingResource,以便在成功加载图像后运行ViewMatcher

从导航Picasso源代码开始,我不明白为什么这不起作用。这就是我的尝试:

Picasso picasso = new Picasso.Builder(context).build();
Field dispatcherField = Picasso.class.getDeclaredField("dispatcher");
dispatcherField.setAccessible(true);

try {
  Dispatcher dispatcher = (Dispatcher) dispatcherField.get(picasso);
  Espresso.registerLooperAsIdlingResource(dispatcher.dispatcherThread.getLooper());
} catch (NoSuchFieldException e) {
  throw new PicassoHasBeenRefactoredException();
} catch (Exception e) {
  e.printStackTrace();
}

onView(withId(R.id.image_view)).check(matches(withImage(R.drawable.drawable)));

(是的,我知道,反映是icky,但我无法找到另一种方法来处理Looper

但尝试从Bitmap获取ImageView时会导致此错误:

java.lang.NullPointerException: Attempt to invoke virtual method 'android.graphics.Bitmap android.graphics.drawable.BitmapDrawable.getBitmap()' on a null object reference

要在加载图片后检查测试是否按预期运行,我尝试使用Thread.sleep(1000)代替IdlingResource检查并通过。

假设IdlingResource没有正确设置是否安全,更重要的是,在使用Espresso检查视图之前,等待Picasso完成加载的正确方法是什么?

1 个答案:

答案 0 :(得分:2)

我正在使用IdlingResource检查是否还有操作​​。

请注意,IdlingResource必须与Picasso位于同一个程序包中才能访问受程序包保护的变量

package com.squareup.picasso;

public class PicassoIdlingResource implements IdlingResource, ActivityLifecycleCallback {
  protected ResourceCallback callback;

  WeakReference<Picasso> picassoWeakReference;

  @Override
  public String getName() {
    return "PicassoIdlingResource";
  }

  @Override
  public boolean isIdleNow() {
    if (isIdle()) {
      notifyDone();
      return true;
    } else {
      return false;
    }
  }

  public boolean isIdle() {
    return picassoWeakReference == null
            || picassoWeakReference.get() == null
            || picassoWeakReference.get().targetToAction.isEmpty();
  }

  @Override
  public void registerIdleTransitionCallback(ResourceCallback resourceCallback) {
    this.callback = resourceCallback;
  }

  void notifyDone() {
    if (callback != null) {
      callback.onTransitionToIdle();
    }
  }

  @Override
  public void onActivityLifecycleChanged(Activity activity, Stage stage) {
    switch (stage) {
      case CREATED:
        picassoWeakReference = new WeakReference<>(Picasso.with(activity));
        break;
      case STOPPED:
        // Clean up reference
        picassoWeakReference = null;
        break;
      default: // NOP
    }
  }
}

我不认为需要使用WeakReference,但它也不会受到伤害。

此外,我已经确定了一个案例,它不会等到毕加索完成(当使用 .load(null)时)。因此,使用风险自负,如果您改进,请回来。

请参阅要点以获取完整的详细信息和用法(https://gist.github.com/Maragues/0c0db81a137c8d067396