Reputation: 83
I have written an Android instrumentation test that calls my service and receives an answer via an broadcast.
The code to be tested, which speaks to the service, uses handler.
In process of testing my test ^^ I noticed that the handlers are not behaving as expected. So I've written an test to check on this behaviour:
import android.os.Handler;
import android.support.test.annotation.UiThreadTest;
import org.junit.Assert;
import org.junit.Test;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@RunWith(AndroidJUnit4.class)
public class HandlerTest {
private CountDownLatch countDownLatch;
@Test
@UiThreadTest
public void handlerTest() {
final Handler handler = new Handler();
countDownLatch = new CountDownLatch(1);
final Runnable r = new Runnable() {
@Override
public void run() {
// this code gets not executed
countDownLatch.countDown();
}
};
handler.postDelayed(r, 1000);
try {
final boolean finishedWithoutTimeout
= countDownLatch.await(5, TimeUnit.SECONDS);
Assert.assertTrue(finishedWithoutTimeout);
} catch (final InterruptedException e) {
e.printStackTrace();
}
}
}
The handler dosn't execute the runnable code. This is also the problem with my production code.
I got a problem with Looper.prepare()
that I fixed with the @UiThreadTest
annotation.
Are there any suggestions regarding my handler problem?
Upvotes: 2
Views: 1047
Reputation: 5096
The reason is that you locked your thread
here:
final boolean finishedWithoutTimeout = countDownLatch.await(5, TimeUnit.SECONDS);
And when the thread
is locked, you can't send a rannable
with your handler
. The Thread
is just locked.
You can solve it by linking your handler
to another thread
. Here is a simple solution via handlerThread
:
@Test
@UiThreadTest
public void handlerTest() {
countDownLatch = new CountDownLatch(1);
final HandlerThread handlerThread = new HandlerThread("solution!");
handlerThread.start();
final Runnable r = new Runnable() {
@Override
public void run() {
countDownLatch.countDown();
}
};
Handler handler = new Handler(handlerThread.getLooper());
handler.postDelayed(r, 1000);
try {
final boolean finishedWithoutTimeout = countDownLatch.await(5, TimeUnit.SECONDS);
Assert.assertTrue(finishedWithoutTimeout);
} catch (final InterruptedException e) {
e.printStackTrace();
}
}
Upvotes: 1