I'm using robolectric to test my AsyncTask class. In the test it does what I expect when the task is run like so:
asyncTask.execute()
But when I do
asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR)
it doesn't (in both instances I run
Robolectric.runUiThreadTasksIncludingDelayedTasks()
Anyone have any idea why calling executeOnExecutor doesn't trigger Robolectric to run but execute works fine?
The Robolectric framework cannot work out of the box with the default executors (i.e. either AsyncTask.THREAD_POOL_EXECUTOR or AsyncTask.SERIAL_EXECUTOR), nor with custom ones.
To solve this issue, you can take one of these two approaches, depending of whether you have control over the executor the tested unit uses. If the answer is YES, the first approach would be to simply get it to use RoboExecutorService (or if using versions under 3.0 - RobolectricBackgroundExecutorService). Otherwise, you'll have to take a different approach which is to apply this 2-steps workaround:
The first thing you need to do is to implement an AsyncTask
shadow that overrides execution on custom executors:
@Implements(AsyncTask.class)
public class MyShadowAsyncTask<Params, Progress, Result> extends ShadowAsyncTask<Params, Progress, Result> {
@Implementation
public AsyncTask<Params, Progress, Result> executeOnExecutor(Executor executor, Params... params) {
return super.execute(params);
}
}
In each test case running production code that uses AsyncTask#executeOnExecutor()
, register your custom shadow to override Robolectric's default, this way (review the 'config' annotation):
@RunWith(RobolectricTestRunner.class)
@Config(shadows={MyShadowAsyncTask.class})
public class MyTest {
// ... test code
}
Consequent calls to Robolectric.runUiThreadTasks()
or Robolectric.runUiThreadTasksIncludingDelayedTasks()
would work as you'd expect (namely, would block the runner thread till async tasks complete).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With