Jason, here is the solution I am using, and it seems to work well. You
are basically still doing the testing on the test thread, but when it
comes time to call the asynctask we switch to the ui thread, and block
the testing thread. When the UI thread is done, it releases the
testing thread and you can continue your test case.
- Billy
/**
* This demonstrates how to test AsyncTasks in android JUnit.
Below I used
* an in line implementation of a asyncTask, but in real life you
would want
* to replace that with some task in your application.
* @throws Throwable
*/
public void testSomeAsynTask () throws Throwable {
// create a signal to let us know when our task is done.
final CountDownLatch signal = new CountDownLatch(1);
/* Just create an in line implementation of an asynctask. Note
this
* would normally not be done, and is just here for
completeness.
* You would just use the task you want to unit test in your
project.
*/
final AsyncTask<String, Void, String> myTask = new
AsyncTask<String, Void, String>() {
@Override
protected String doInBackground(String... arg0) {
//Do something meaningful.
return "something happened!";
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
/* This is the key, normally you would use some type
of listener
* to notify your activity that the async call was
finished.
*
* In your test method you would subscribe to that and
signal
* from there instead.
*/
signal.countDown();
}
};
// Execute the async task on the UI thread! THIS IS KEY!
runTestOnUiThread(new Runnable() {
@Override
public void run() {
myTask.execute("Do something");
}
});
/* The testing thread will wait here until the UI thread
releases it
* above with the countDown() or 30 seconds passes and it
times out.
*/
signal.await(30, TimeUnit.SECONDS);
// The task is done, and now you can assert some things!
assertTrue("Happiness", true);
}
On Apr 5, 4:28 pm, Jason <[email protected]> wrote:
> OK.. So after re-thinking this I realized why the problem is
> occurring, although I still do not have a solution.
>
> When the test is running it seems to be treating itself as the main UI
> thread, which would make sense since it's an
> ActivityInstrumentationTestCase2. The AsyncTask performs the
> necessary callbacks in the onPostExecute method, which also runs on
> the main UI thread.
>
> Because my test is entering a wait loop so it ensures the AsyncTask
> has completed, it is essentially blocking the main UI thread and the
> onPostExecute method cannot execute.
>
> So.. the question becomes.. how do we assert the results of an
> AsyncTask inJUnit? We can't wait for theAsynctask to complete for
> the reasons described above, and I don't want to move my callback code
> to the doInBackground method because in the "real world" I need/want
> the callback to be on the main UI thread.
>
> Hopefully someone out there has a pattern for asserting asynctask
> outcomes in a test case...
>
> Thanks.
>
> On Apr 5, 1:46 pm, Jason <[email protected]> wrote:
>
>
>
>
>
>
>
> > Hi,
>
> > Missed your response. This didn't work for me unfortunately.
>
> > Interestingly if I mark the test with @UiThreadTest I get the same
> > deadlock behavior, which makes me wonder whether there is some sort
> > ofJUnittest state being re-used when the test is run in a suite?
>
> > As it stands I have a bunch of important test cases that I'm having to
> > just comment out because they hang when run in the suite (although
> > they all run and pass when executed individually).
>
> > I feel like I've tried everything to get these to work, but clearly
> > I'm missing something here.
>
> > Any other ideas?
>
> > Thanks,
>
> > Jason.
>
> > On Mar 17, 7:59 pm, Streets Of Boston <[email protected]> wrote:
>
> > >JUnittest-methods in the instrumentation test-case classes always run in
> > > another thread than the main UI thread. I run both indiviual test-cases
> > > and
> > > test-suites (that execute lists of test-cases) and test-methods are always
> > > called in a different thread than the background thread.
>
> > > I read this in your original question: "*... This method call (internally)
> > > launches an AsyncTask ...*". I ran into a problem and this may be related
> > > to
> > > your issue:
> > > You have to *create the first AsyncTask of your (test-)process in the main
> > > UI thread*. If you don't do this, and the (first) AsyncTask is created in
> > > a
> > > non-UI thread (e.g. during a testXXXX() method), weird stuff can happen.
> > > In
> > > other words: Be sure that the VM loads the AsyncTask *class* in the main
> > > UI
> > > thread. From then on, you can create and execute AsynTasks in any thread.
>
> > > E.g in your first test's setup or the first testXXXXX() method:
> > > ...
> > > runTestOnUIThread(new Runnable() {
> > > public void run() {
> > > new AsyncTask(); // just create one and let it go; doing this makes
> > > sure that the class loads in the main UI thread.
> > > }
> > > }
> > > ...
> > > ... // now you're free to create and execute AsyncTasks (directly or
> > > through other method calls).
>
> > > Maybe this problem is related to the one you see.
--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en