Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is there no test instrumentation for BroadcastReceiver?

Maybe I'm missing something. I want to write test cases for a BroadcastReceiver; specifically, it is for receiving the BOOT_COMPLETED event and setting an alarm for another receiver to handle later; it doesn't seem to be setting it properly, but the point is that I have no obvious way to test it. I can't exactly attach a debugger and wait for BOOT_COMPLETED, and I can't send a fake BOOT_COMPLETED broadcast.

Why are there instrumentation classes for Activity, Service, and Provider, but not BroadcastReceiver? Any advice for testing this?

like image 479
sosiouxme Avatar asked Nov 01 '10 23:11

sosiouxme


2 Answers

There is nothing magical about the life cycle for the BroadcastReceiver. It's enough to test it with an AndroidTestCase. In a test case, instantiate your BroadcastReceiver, create whatever Intent you want to send and call onReceive using the Context available from AndroidTestCase or some mock Context.

E.g.

public class TestMyBroadcastReceiver extends AndroidTestCase {
  public void testReceive() {
    MyBroadcastReceiver r = new MyBroadcastReceiver();
    Intent i = new Intent("MY_ACTION");
    // TODO put extras
    r.onReceive(getContext(), i);
    // TODO query application state to verify results
  }
}
like image 116
David Burström Avatar answered Oct 24 '22 11:10

David Burström


For most cases I agree completely with https://stackoverflow.com/a/5181010/527016

There are however cases when extending AndroidTestCase is not suitable (and can cause surprises). In particular, if you are doing more complex integration testing and want to test your BroadcastReceiver with an actual Intent sent by the system. The main reason is that the onReceive method in the broadcast receiver runs on the main application thread while the tests in AndroidTestCase run in another thread. This can cause test-related threading issues in code that was not intended to run on multiple threads.

The solution to this is to subclass your test from InstrumentationTestCase instead and use the @UiThreadTest annotation to make the tests run on the same thread as the onReceive method.

For more info (and an example) see: http://olafurhelgason.blogspot.com/2012/12/threading-and-android-integration.html

like image 45
Olafur Helgason Avatar answered Oct 24 '22 09:10

Olafur Helgason