IdlingResource Espresso with RxJava

2019-03-12 20:26发布

I recently converted my application from using async tasks to rxjava. Now, my espresso tests no longer wait for my data calls to complete due to espresso not having an idling resources for rxjava. I noticed that you can make custom idling resources but I can't figure out how to make it work with rxJava Schedulers, Scheduler.io specifically. Any help/best practice would be greatly appreciated.

3条回答
Animai°情兽
2楼-- · 2019-03-12 20:43

I am currently using this implementation. Its easier and works very well for me so far: https://github.com/rosshambrick/RxEspresso

查看更多
小情绪 Triste *
3楼-- · 2019-03-12 21:08

Here is how I solved the problem:

IdlingResource implementation:

public class IdlingApiServiceWrapper implements MyRestService, IdlingResource {

private final MyRestService           api;
private final AtomicInteger counter;
private final List<ResourceCallback> callbacks;

public IdlingApiServiceWrapper(MyRestService api) {
    this.api = api;
    this.callbacks = new ArrayList<>();
    this.counter = new AtomicInteger(0);
}

public Observable<MyData> loadData(){
    counter.incrementAndGet();
    return api.loadData().finallyDo(new Action0() {
        @Override
        public void call() {
            new Handler(Looper.getMainLooper()).post(new Runnable() {
                @Override
                public void run() {
                    counter.decrementAndGet();
                    notifyIdle();
                }
            });
        }
    });
}

@Override public String getName() {
    return this.getClass().getName();
}

@Override public boolean isIdleNow() {
    return counter.get() == 0;
}

@Override public void registerIdleTransitionCallback(ResourceCallback resourceCallback) {
    callbacks.add(resourceCallback);
}

private void notifyIdle() {
    if (counter.get() == 0) {
        for (ResourceCallback cb : callbacks) {
            cb.onTransitionToIdle();
        }
    }
   }
   }

and here is my test:

public class MyActivityTest extends ActivityInstrumentationTestCase2<MyActivity> {
@Inject
IdlingApiServiceWrapper idlingApiWrapper;

@Override
public void setUp() throws Exception {
    //object graph creation

    super.setUp();
    getActivity();
    Espresso.registerIdlingResources(idlingApiWrapper);
}

public void testClickOpenFirstSavedOffer() throws Exception {
    onData(is(instanceOf(DataItem.class)))
            .atPosition(0)
            .perform(click());
   }
  }

I used Dagger for dependency injection.

查看更多
Explosion°爆炸
4楼-- · 2019-03-12 21:08

Wrote a little integration piece between RxJava Plugins and Espresso. Hope this helps someone else.

https://gist.github.com/digitalbuddha/d886eae1578bca78b9bf

Edit:

There is a much easier way to accomplish this task. Add the following rule to your tests

public class AsyncTaskSchedulerRule implements TestRule {
    final Scheduler asyncTaskScheduler = Schedulers.from(AsyncTask.THREAD_POOL_EXECUTOR);

    @Override
    public Statement apply(Statement base, Description description) {
        return new Statement() {
            @Override
            public void evaluate() throws Throwable {
                RxJavaHooks.setOnIOScheduler(scheduler -> asyncTaskScheduler);
                RxJavaHooks.setOnComputationScheduler(scheduler -> asyncTaskScheduler);
                RxJavaHooks.setOnNewThreadScheduler(scheduler -> asyncTaskScheduler);
                try {
                    base.evaluate();
                } finally {
                    RxJavaHooks.reset();
                }
            }
        };
    }
}
查看更多
登录 后发表回答