how to make assert to wait for IdlingResource to a

2019-09-16 12:03发布

I want to use idling resources because I´m using RxJava and EventBus in my app and sometimes my tests fail (I´m thinking that is because that synchronisation).

Dependencies:

androidTestCompile 'com.android.support.test:runner:0.4'
androidTestCompile 'com.android.support.test:rules:0.4'
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.1'
androidTestCompile 'com.android.support.test.espresso:espresso-intents:2.2.1'
androidTestCompile('com.android.support.test.espresso:espresso-contrib:2.2.1') {
    exclude group: 'com.android.support', module: 'appcompat'
    exclude group: 'com.android.support', module: 'support-v4'
    exclude module: 'recyclerview-v7'
}
androidTestCompile 'junit:junit:4.12'
androidTestCompile 'com.squareup.retrofit:retrofit-mock:1.9.0'
androidTestCompile 'com.squareup.assertj:assertj-android:1.1.0'
androidTestCompile 'com.squareup.spoon:spoon-client:1.2.0'

Test failing:

@RunWith(AndroidJUnit4.class)
@SmallTest
public class PushNotificationTests {

    @Test
    public void testSomething(){

        // do things...
        MyIdlingResource eventBusIdlingResource = new MyIdlingResource();
        registerIdlingResources(eventBusIdlingResource);

        Order.Status status = Order.getCurrentObservable().toBlocking().first().getStatus();
        assertThat(status).isEqualTo(Order.Status.PROGRESS);   // Fail,

        unregisterIdlingResources(eventBusIdlingResource)
    }

}

Try but not working:

@RunWith(AndroidJUnit4.class)
@SmallTest
public class PushNotificationTests {

    @Test
    public void testSomething(){

        // do things...

        MyIdlingResource eventBusIdlingResource = new MyIdlingResource();
        registerIdlingResources(eventBusIdlingResource);

        // Wait manually?
        int sleeps = 0;
        while(!eventBusIdlingResource.isIdleNow() || sleeps < 10){
            sleep(100);
            sleeps++;
        }

        Order.Status status = Order.getCurrentObservable().toBlocking().first().getStatus();
        assertThat(status).isEqualTo(Order.Status.PROGRESS);   // Fail,

        unregisterIdlingResources(eventBusIdlingResource)
    }

}

3条回答
Deceive 欺骗
2楼-- · 2019-09-16 12:22

I know this is an old question, but I ran across this while searching and thought other people might too. This behavior is now built-in into Espresso.onIdle().

void onIdle ()

Loops the main thread until the app goes idle.

Only call this method for tests that do not interact with any UI elements, but require Espresso's main thread synchronisation! This method is mainly useful for test utilities and frameworks that are build on top of Espresso.

For UI tests use onView(Matcher) or onData(Matcher). These Apis already use Espresso's internal synchronisation mechanisms and do not require a call to onIdle().

https://developer.android.com/reference/android/support/test/espresso/Espresso#onidle

查看更多
三岁会撩人
3楼-- · 2019-09-16 12:27

End up encapsulating the sleep method inside a class.

import android.support.test.espresso.IdlingResource;

/**
 * Have functions to sleep the processor because assertions are not linked to
 * {@link IdlingResource} to do assertions, so should be used before asserts if there's an
 * idle process.
 */
public class IdlingResourceSleeper {

    private static final int SLEEPS_LIMIT = 50;
    private static final int SLEEPS_TIME = 10;

    /**
     * Used to sleep {@link IdlingResourceSleeper#SLEEPS_LIMIT} times and
     * {@link IdlingResourceSleeper#SLEEPS_TIME} ms until idlingResource.isIdleNow() is false.
     *
     * @param idlingResource
     */
    public static void sleep(IdlingResource idlingResource) {
        int sleeps = 0;
        while (!idlingResource.isIdleNow() || sleeps < SLEEPS_LIMIT) {
            android.os.SystemClock.sleep(SLEEPS_TIME);
            sleeps++;
        }

    }
}

sources: - gist - post

查看更多
劳资没心,怎么记你
4楼-- · 2019-09-16 12:42

I had the same requirement to force Espresso to being idle before I checked the state of the UI. What worked for me, is to add an always true view assertion, since Espresso waits for idle state before executing it.

onView(isRoot()).check(matches(anything()));
查看更多
登录 后发表回答