监控 Picasso 在 Espresso 中的 IdlingResource
Posted
技术标签:
【中文标题】监控 Picasso 在 Espresso 中的 IdlingResource【英文标题】:Monitoring Picasso for IdlingResource in Espresso 【发布时间】:2015-09-25 09:53:43 【问题描述】:我希望能够将Espresso
监视Picasso
作为IdlingResource
,以便在成功加载图像后我可以运行ViewMatcher
s。
通过浏览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)));
(是的,我知道,反射很恶心,但我找不到其他方法来处理Looper
)
但是在尝试从ImageView
获取Bitmap
时会导致这个错误:
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 完成加载的正确方法是什么?
【问题讨论】:
你不能使用 Picasso 的 onSucess callback 来设置你的 IdelingResource 吗? @RahulTiwari 我不想修改任何生产代码来适应测试,除非你的意思是别的? 我说的是使用 Picasso 提供的回调函数onSuccess
和 onError
并尽可能摆脱反射。所以是的,我说的是修改代码,但它肯定不会影响任何功能。
这是一个权衡。在我看来,在生产代码上设置一个 idlingResource 是非常无害的,并且会引导您获得更简单的测试代码。
【参考方案1】:
我正在使用 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)
【讨论】:
谢谢!在活动之间移动时,该解决方案无法正常工作。为了解决这个问题,我将状态 CREATED & STOPPED 替换为 RESUMED & PAUSED 我还发现这会引入很大的延迟(每个加载的图像最多延迟 5 秒),因为 Espresso 在重新检查之间有几秒钟的延迟。解决方案是强制重新检查 PicassoIdlingResource,如下例所示:gist.github.com/vaughandroid/… 谢谢@SebasLG,我目前正在处理另一个项目,但一旦我回到旧代码,我会检查你的代码。以上是关于监控 Picasso 在 Espresso 中的 IdlingResource的主要内容,如果未能解决你的问题,请参考以下文章
如何与 Espresso 中的 alertdialog 交互?
Android Studio 2.2 中的 Espresso 测试录制功能