Back in 1.9, in order to let Espresso know when the app was idle, as per this SO answer, you'd change the RestAdapter's thread-pool executor with the same as AsyncTask.
new RestAdapter.Builder()
.setExecutors(AsyncTask.THREAD_POOL_EXECUTOR, new MainThreadExecutor())
It kinda seems more like a hackz than the actual way of doing it, so I think that's probably the reason the method setExecutors() is not part of the public API anymore on retrofit 2.0, which is nice.
Now, we still need to make it work somehow with Espresso for our tests, right? Looking into retrofit-mock tests, I was able to see there's a class called CallBehaviourAdapter that goes like this:
NetworkBehavior.Adapter<?> adapter = new CallBehaviorAdapter(retrofit, newSingleThreadExecutor());
MockRetrofit mockRetrofit = new MockRetrofit(behavior, adapter);
service = mockRetrofit.create(DoWorkService.class, mockService);
I think what would do the trick is the newSingleThreadExecutor() call but after trying for a couple of hours I found myself unable to accomplish it.
Moreover, in the SimpleMockService sample there is the same call with a ThreadFactoryBuilder:
Executors.newSingleThreadExecutor(new ThreadFactoryBuilder()
.setNameFormat("mock-retrofit-%d")
.setDaemon(true)
.build());
Tried both but they didn't work. What am I missing?
Does Espresso not have a way to wrap an Executor in an IdlingResource?
Filed http://b.android.com/187510. See also http://stefanodacchille.github.io/blog/2014/04/05/wait-for-it/ and the gist https://gist.github.com/stefanodacchille/9995163 for ways to accomplish this.
You should still be able to use the AsyncTask executor for the MockRetrofit class, but you'll need something smarter than that to pass to OkHttp's getDispatcher().setExecutor() because it has specific requirements. It would be nicer to just be able to wrap OkHttp's built-in executor using something like the above.
There's not much else to do here, this isn't really an Retrofit / OkHttp problem, just a shortcoming of the tools Espresso provides.
if you're using Observables you can use .subscribeOn(Schedulers.from(AsyncTask.THREAD_POOL_EXECUTOR)) instead of .subscribeOn(Schedulers.io()) and everything works fine
Or wrap the Action using RxJavaSchedulersHook
I just put this in my instrumentation test runner's onStart():
RxJavaHooks.setOnIOScheduler(new Func1<Scheduler, Scheduler>() {
@Override
public Scheduler call(Scheduler scheduler) {
return Schedulers.from(AsyncTask.THREAD_POOL_EXECUTOR);
}
});
Where my Retrofit instance uses the IO scheduler by default, and so far it's working great.
@shekibobo I had to put this code in the onCreate() of my custom instrumentation testrunner but then it worked for me. 馃憤
And of course this is not specific to Retrofit (I am using it just for performing some long running operation in the background with Schedulers.io())
Most helpful comment
Or wrap the
ActionusingRxJavaSchedulersHook