为什么 androidx espresso .check() 导致 androidx.test.espresso.IdlingResourceTimeoutException
Why is androidx espresso .check() causing androidx.test.espresso.IdlingResourceTimeoutException
我有一些使用 androidx Espresso 的单元测试 每次我 运行 测试我都会收到以下错误。
androidx.test.espresso.IdlingResourceTimeoutException: Wait for [WorkTrackerIdlingResource] to become idle timed out
为什么我会超时?
在我的单元测试中,这行代码超时,
onView(withId(R.id.map_container)).check(matches(isDisplayed()));
单元测试Class:
@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>
我已经尝试更改空闲首选项以便超时为 5 分钟,但我仍然收到错误消息。
编辑 1
根据要求,我添加了代码,我在下面 class 的底部添加了 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);
}
这里简要解释一下为什么你的测试总是超时:你设置了一个测试规则,在测试开始之前注册一个空闲资源,然后当你的activity启动时,主线程变得繁忙。通常,当主线程空闲时测试将继续,但您的空闲资源现在阻塞它并且不调用 onTransitionToIdle。所以无论你设置多少时间,它都会超时。
我认为您在这里使用空闲资源可能没有用或不正确。如果没有用例,你可以去掉规则,它应该可以正常工作。
我有一些使用 androidx Espresso 的单元测试 每次我 运行 测试我都会收到以下错误。
androidx.test.espresso.IdlingResourceTimeoutException: Wait for [WorkTrackerIdlingResource] to become idle timed out
为什么我会超时?
在我的单元测试中,这行代码超时,
onView(withId(R.id.map_container)).check(matches(isDisplayed()));
单元测试Class:
@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>
我已经尝试更改空闲首选项以便超时为 5 分钟,但我仍然收到错误消息。
编辑 1
根据要求,我添加了代码,我在下面 class 的底部添加了 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);
}
这里简要解释一下为什么你的测试总是超时:你设置了一个测试规则,在测试开始之前注册一个空闲资源,然后当你的activity启动时,主线程变得繁忙。通常,当主线程空闲时测试将继续,但您的空闲资源现在阻塞它并且不调用 onTransitionToIdle。所以无论你设置多少时间,它都会超时。
我认为您在这里使用空闲资源可能没有用或不正确。如果没有用例,你可以去掉规则,它应该可以正常工作。