I have a problem with unit tests in Android.
My object MyObject has a method start() like this :
public void start() {
final Handler onStartHandler = new Handler();
new Thread() {
@Override
public void run() {
super.run();
onStartHandler.post(new Runnable() {
@Override
public void run() {
mIsRunning = true;
onStart();
}
});
}
}.start();
}
And I want to test that onStart() is called.
So I tried something like that :
public void testOnStartIsCalled() {
assertFalse("onStart() should not be called", mMyObject.isRunning());
mMyObject.start();
assertTrue("onStart() should be called", mMyObject.isRunning());
mMyObject.stop();
assertFalse("onStop() should be called", mMyObject.isRunning());
}
But it doesn’t work, I guess it’s because it’s in a Handler and a new Thread.
My test class extends AndroidTestCase.
What should I do ? What is the best practice for this case ?
Regards.
When I deal with testing some multi-threaded code I try to let the program take as much of its natural flow as possible. Additionally, I avoid the use of sleep statements since you don’t get any guarantees that the sleep interval you’ve chosen is enough to allow the subject of your test to finish what it’s doing; you often end up having to choose sleep intervals that are too large and it forces a much slower execution of your test cases.
I would recommend that you try to add some code into the class you’re testing, in this case
MyObject, which call a listener whenever something happens. It seems that you already have callback methods foronStart()andonStop()(if those are events/callbacks), so those should be getting invoked and you should use them to control the flow of your test. When you get anonStart()event, you should then callstop()and wait for anonStop()event.Update
First and foremost, you have redundant code:
Either start a new thread to call
onStart()or schedule the runnable on the Handler’s thread queue.Version 1- remove the handler and just let the code be executed in a new thread:
Version 2- only use the handler to asynchronously execute the callback:
And second: I noticed is that if you don’t have a Looper, then whatever you post with the
Handlerwill be ignored (thus it will never be called). For more information on the Looper-Handler pattern see the article: Android Guts: Intro to Loopers and Handlers. TheLooperand theHandlerare supposed to be attached to the same thread (usually the main thread). Additionally, if you’re creating theHandleron a separate thread as yourLooper, then you’ll run into the same problem: anything you post with theHandlerwill be ignored.Here are a few more good questions and articles on loopers and handlers:
The relationships between Looper, Handler and MessageQueue is shown below:
