Android Unit Testing with AsyncTask and UI Updates Solution
Asked Answered
E

2

6

Scenario:

I'm trying to unit test the onClick handler of my application. Onclick does a simple search against a REST API, returns the results and updates the UI.

Details:

Onclick executes an AsyncTask, the doInBackground queries the REST API and returns the results. The onPostExecute takes the results and assigns a new ListAdapter to the ListView with the data.

Problem:

The onPostExecute doesn't get called in by the Test Runner since it's on the same UI Thread and blocks the call. There are several patterns for dealing with this. However, if I put the AsyncTask in a Runnable and use the LatchCountdown to wait for the result, I get the CalledFromWrongThread Exception.

Is there a good solution to unit testing an AsyncTask that does UI updates? Or a more testable design that I can implement?

Edwinaedwine answered 16/11, 2012 at 14:50 Comment(5)
This sounds more like an ActivityInstrumentationTestCase to me...Capua
This is being done in an ActivityInstrumentationTestCase2 class.Edwinaedwine
Your asynctask should run fine then...Capua
@Capua it was erroring out with CalledFromWrongThread Exception when doing the UI update.Edwinaedwine
Oh i see where it was errorring out then. Hmmm something is fishy... but if it works for you....Capua
E
0

Ok, so the solution I came up with is this:

1.) Define a listener interface for the pre & post events.
2.) Implement listener on Activity
2.) Define a task wrapper class that accepts a listener and who has an inner AsyncTask that is called on 'exec'.
3.) The inner AsyncTask notifies the listener on onPreExecute and onPostExecute
4.) Upon notification, the Activity updates it's UI.

For testing in the Activity:
1.) Create a serial version of the wrapper class by inheriting from it, then overriding the exec method to execute in sequence:
- notify listener the task as started.
- execute the task.
- notify the listener the task is complete.

For testing the Asynchronous version of the task.
1.) Use a CountdownLatch and Runnable in the unit test method. Since there wont' be any UI updates needed, you wont' have any WrongThreadExceptions.

Edwinaedwine answered 16/11, 2012 at 19:30 Comment(1)
You are probably interesting on similar discussion here and here.Emendate
E
0

You want to run the test on the Ui Thread

runOnUiThread(new Runnable() {
   public void run() {
      onPostExecute(...)

  }
});
Encyst answered 16/11, 2012 at 14:56 Comment(0)
E
0

Ok, so the solution I came up with is this:

1.) Define a listener interface for the pre & post events.
2.) Implement listener on Activity
2.) Define a task wrapper class that accepts a listener and who has an inner AsyncTask that is called on 'exec'.
3.) The inner AsyncTask notifies the listener on onPreExecute and onPostExecute
4.) Upon notification, the Activity updates it's UI.

For testing in the Activity:
1.) Create a serial version of the wrapper class by inheriting from it, then overriding the exec method to execute in sequence:
- notify listener the task as started.
- execute the task.
- notify the listener the task is complete.

For testing the Asynchronous version of the task.
1.) Use a CountdownLatch and Runnable in the unit test method. Since there wont' be any UI updates needed, you wont' have any WrongThreadExceptions.

Edwinaedwine answered 16/11, 2012 at 19:30 Comment(1)
You are probably interesting on similar discussion here and here.Emendate

© 2022 - 2024 — McMap. All rights reserved.