I am writing a unit test for a service using ServiceTestCase.
The service basically executes an AsyncTask that does some work and then does something else in onPostExecute().
The service works as expected when I run and debug it in a (virtual) device.
But in the test extending ServiceTestCase, I only get into doInBackground(). Once the methods returns, onPostExecute() never gets called. I am letting the test sleep() so the AsyncTask has time to complete its work.
This is the simplified service:
public class ServiceToTest extends Service {
private AtomicBoolean busy = new AtomicBoolean(false);
@Override
public IBinder onBind(final Intent intent) {
return null;
}
@Override
public int onStartCommand(final Intent intent, final int flags,
final int startId) {
this.handleCommand();
return START_NOT_STICKY;
}
/**
* Workaround for http://code.google.com/p/android/issues/detail?id=12117
*/
@Override
public void onStart(final Intent intent, final int startId) {
this.handleCommand();
}
public void handleCommand() {
new TaskToTest().execute();
}
public boolean isBusy() {
return busy.get();
}
private class TaskToTest extends AsyncTask<Boolean, Void, TestInfo> {
@Override
protected void onPreExecute() {
busy.set(true);
}
@Override
protected TestInfo doInBackground(final Boolean... args) {
return null;
}
@Override
protected void onPostExecute(final TestInfo info) {
busy.set(false);
}
}
}
An this is the test for it:
public class ServiceTest extends ServiceTestCase<ServiceToTest> {
public ServiceTest() {
super(ServiceToTest.class);
}
public void testIsBusy() throws InterruptedException {
startService(new Intent("this.is.the.ServiceToTest"));
ServiceToTest serviceToTest = this.getService();
assertTrue(serviceToTest.isBusy());
Thread.sleep(10000);
assertFalse(serviceToTest.isBusy());
}
}
I suppose that the environment provided by ServiceTestCase is somewhat limited so this doesn't work, but is there anything I can do to make it work anyway?
Cheers, Torsten
The problem is that your background thread is waiting for the UI to be "alive", you need to call Looper.prepare()
and Looper.loop()
. It's better explained in this page.