我有一个ListView,它的每个项目都有一个ImageView。我正在使用Picasso将网络中的照片加载到每个图像视图中。
我正在尝试使用espresso为此ListView编写功能测试。经过一段时间的努力,我发现我可以使用:
滚动到ListView中的项目onData(instanceOf(Item.class))
.inAdapterView(allOf(withId(android.R.id.list), isDisplayed()))
.atPosition(14)
.check(matches(isDisplayed()));
运行测试后,列表将滚动到该项目,但会因以下异常而崩溃:
java.lang.NullPointerException
at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1052)
at android.view.View.layout(View.java:14841)
at android.view.ViewGroup.layout(ViewGroup.java:4631)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
at android.view.View.layout(View.java:14841)
at android.view.ViewGroup.layout(ViewGroup.java:4631)
at android.support.v4.view.ViewPager.onLayout(ViewPager.java:1594)
at android.view.View.layout(View.java:14841)
at android.view.ViewGroup.layout(ViewGroup.java:4631)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
at android.view.View.layout(View.java:14841)
at android.view.ViewGroup.layout(ViewGroup.java:4631)
at com.android.internal.widget.ActionBarOverlayLayout.onLayout(ActionBarOverlayLayout.java:374)
at android.view.View.layout(View.java:14841)
at android.view.ViewGroup.layout(ViewGroup.java:4631)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
at android.view.View.layout(View.java:14841)
at android.view.ViewGroup.layout(ViewGroup.java:4631)
at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:1987)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1744)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1000)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5670)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:761)
at android.view.Choreographer.doCallbacks(Choreographer.java:574)
at android.view.Choreographer.doFrame(Choreographer.java:544)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:747)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at com.google.android.apps.common.testing.ui.espresso.base.UiControllerImpl.loopUntil(UiControllerImpl.java:467)
at com.google.android.apps.common.testing.ui.espresso.base.UiControllerImpl.loopUntil(UiControllerImpl.java:383)
at com.google.android.apps.common.testing.ui.espresso.base.UiControllerImpl.loopMainThreadForAtLeast(UiControllerImpl.java:368)
at se.saltside.monterosa.util.ViewMatchers$4.perform(ViewMatchers.java:117)
at com.google.android.apps.common.testing.ui.espresso.ViewInteraction$1.run(ViewInteraction.java:119)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5149)
at java.lang.reflect.Method.invokeNative(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:605)
at dalvik.system.NativeStart.main(Native Method)
经过调查,完成代码和一些试验后,我使用 getView
将问题的根源缩小到我的适配器Picasso
中加载图像的行:
Picasso.with(getContext()).load(ad.getDefaultImage().getThumbnailUrl()).into(imageView);
关于为什么会发生这种情况以及如何解决问题的任何想法?
注意:
我也尝试过实现自己的ViewAction,它会滚动到ListView中的给定项目。但我得到了同样的结果。
上面的堆栈跟踪来自android 4.4.2 CyagonenMod版本。在4.4.4 Nexus上,堆栈跟踪是相同的,除了提供更多信息的标题:
java.lang.NullPointerException: Attempt to invoke virtual method 'int android.view.View.getVisibility()' on a null object reference
更新
似乎问题比毕加索更大。如果我评论毕加索,测试平均失败5次,而毕加索则失败了5次中的4次。我甚至过度简化了我的getView
,看看会发生什么,并且每5次运行就会失败一次:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final View view;
if (convertView == null) {
view = LayoutInflater.from(mContext).inflate(layoutResId, parent, false);
} else {
view = convertView;
}
return view;
}