【发布时间】:2018-11-07 21:20:20
【问题描述】:
我使用 androidx Espresso 进行了一些单元测试,每次运行测试时都会出现以下错误。
androidx.test.espresso.IdlingResourceTimeoutException: Wait for [WorkTrackerIdlingResource] to become idle timed out
为什么我会超时?
它在我的单元测试中的这行代码超时,
onView(withId(R.id.map_container)).check(matches(isDisplayed()));
单元测试类:
@RunWith(AndroidJUnit4.class)
@LargeTest
public class CanvassFragmentTest extends TopLevelNavFragmentTest<CanvassFragment> {
@NonNull
@Override
protected TopLevelNavFragment getTargetTopLevelNavFragment(@NonNull MainActivity activity) {
return activity.mCanvassFragment;
}
@Test
public void mapContainer_isDisplayed() {
onView(withId(R.id.id1_container)).check(matches(isDisplayed()));
}
}
还有我们正在尝试测试的具有视图的 xml。
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.company.MapContainerFragment">
<FrameLayout
android:id="@+id/id1_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
.....
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
我已尝试更改 idlepreferences 以使超时为 5 分钟,但我仍然收到错误消息。
编辑 1
根据要求,我添加代码是我在下面这个类的底部添加onTransitionToIdle
public class WaitForWorkRule implements TestRule {
@Override
public Statement apply(Statement base, Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
WorkTrackerIdlingResource idler = new WorkTrackerIdlingResource();
//Espresso.registerIdlingResources(idler);
IdlingRegistry.getInstance().register(idler);
try {
base.evaluate();
} finally {
IdlingRegistry.getInstance().unregister(idler);
}
}
};
}
/**
* @hide visible for injection
*/
public static class WorkTrackerIdlingResource implements IdlingResource {
private static final String TAG = WorkTrackerIdlingResource.class.getSimpleName();
@Inject
WorkTracker mWorkTracker;
@Nullable
ResourceCallback mResourceCallback;
public WorkTrackerIdlingResource() {
getUiTestInjector().inject(this);
}
@Override
public String getName() {
return TAG;
}
@Override
public boolean isIdleNow() {
boolean idle = !mWorkTracker.isAnyoneWorking();
if (idle && mResourceCallback != null) mResourceCallback.onTransitionToIdle();
return idle;
}
@Override
public void registerIdleTransitionCallback(@Nullable ResourceCallback callback) {
mResourceCallback = callback;
}
}
}
这是我们将其注册为规则的代码。
@Rule
public final RuleChain mRuleChain;
public UiTest(@NonNull Class<T> activityClass) {
mActivityTestRule = new ActivityTestRule<>(activityClass);
mRuleChain = createRuleChain();
}
@NonNull
private RuleChain createRuleChain() {
RuleChain chain = RuleChain.emptyRuleChain()
.around(new InjectionRule())
.around(new WaitForWorkRule());
if (loggedIn()) {
chain = chain.around(new LoggedInRule());
}
return chain.around(mActivityTestRule);
}
【问题讨论】:
-
看起来您已经在您的
MainActivity中/从您的MainActivity中注册了一个IdlingResource。您能否发布活动代码或您的注册方式以及您在哪里拨打onTransitionToIdle? -
@Aaron 我已经添加了您要求的代码。
-
这里简要解释一下为什么你的测试超时:你设置了一个测试规则,在测试开始之前注册一个空闲资源,然后当你的活动开始并且主线程变得忙碌时。通常,当主线程空闲时,测试将继续,但您的空闲资源现在阻塞它并且不调用
onTransitionToIdle。我认为您在这里使用空闲资源可能没有用或不正确。你这样做有什么特别的原因吗? -
@Aaron 老实说,我并没有编写代码的规则部分,而 6 个月前离开的开发人员。我删除了该规则,并编译并运行了测试。当我们迁移到 androidx 时,我在想一些根本性的变化。非常感谢你的帮助!如果你想把你的评论变成一个简短的回答,我很乐意接受。
标签: android unit-testing android-espresso