Issue
I have some unit tests using androidx Espresso Every time I run the test I get the following error.
androidx.test.espresso.IdlingResourceTimeoutException: Wait for [WorkTrackerIdlingResource] to become idle timed out
Why am I getting timed out?
Its timing out on this line of code in my unittests,
onView(withId(R.id.map_container)).check(matches(isDisplayed()));
Unit Test 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()));
}
}
And the xml which has the view we are trying to test.
<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>
I've tried changing the idlepreferences so that the timeout is 5 minutes and I still get the error.
EDIT 1
as request I'm adding the code were I add onTransitionToIdle
at the bottom of this class bellow
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;
}
}
}
And this is the code were we register it as a rule.
@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);
}
Solution
Here's a brief explanation why your test always time out: you set a test rule that registers an idling resource before test begins, then when your activity starts, the main thread becomes busy. Generally, the test will continue when the main thread becomes idle, but your idling resource now blocks it and does not call onTransitionToIdle. So no matter how much time you set, it will always time out.
I think your usage of idling resource here may be not useful or incorrect. If there's no use case for it, you can take the rule out and it should work fine.
Answered By - Aaron
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.