Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

asyncTask test doesn't execute

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?

like image 509
Akeem Avatar asked Oct 10 '14 02:10

Akeem


1 Answers

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:

Defining a custom AsyncTask shadow

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);
    }       
}

Registering the custom shadow

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).

like image 61
d4vidi Avatar answered Nov 09 '22 14:11

d4vidi