How to unit test methods sent by Event Bus in android?

I use the Otto event bus in my application. In one of my classes, I am posting an event.

MyEvent myevent = new MyEvent(); uiBus.post(myEvent); 

I can check the post method.

Now there is another class that receives the event.

 //ReceiverClass.java @Subscribe public void onEventReceived(MyEvent myevent) { callAMethod(); } 

How unit test calls this method. I tried with the following test code

 @Mock Bus uiBus; @Test public void testBusReceviedEvent() { ReceiverClass instance = new ReceiverClass(); mockBus.register(instance); MyEvent myevent = new MyEvent(); mockBus.post(myEvent); //Test verify(instance, times(1)).callAMethod(); } 

But this code does not work.

+6
source share
2 answers

I'm a little late to the party, but here is an example of a class that works and takes into account asynchronous calls. Instead of the Mocking EventBus, we just let it do this and register it in the TestDriver class below.

What does this work is a CountDownLatch , which, using the abstract DataTransferCallback class DataTransferCallback waits for latch.countDown() be called, or after 5 seconds.

Just register your test class and @Subscribe method, pass it back to the method that created the DataTransferCallback , and make your statements there.

 @RunWith(AndroidJUnit4.class) public class TestDriver { private final CountDownLatch latch = new CountDownLatch(1); private EventBus eventBus; private DataTransferCallback transferCallback; public abstract class DataTransferCallback { abstract void onSuccess(DataTransfer event); } @Before public void setUp() { EventBus.getDefault().register(this); eventBus = spy(EventBus.getDefault()); } @SuppressWarnings("unchecked") @Test public void test200Resposne() throws InterruptedException { // Get known good JSON final String json = TestJSON.get200Response(); // Class under test final Driver driver = new Driver(InstrumentationRegistry.getTargetContext()); final JsonParser jsonParser = new JsonParser(); //boolean to hold our test result final boolean[] testPassed = new boolean[]{false}; transferCallback = new DataTransferCallback() { @Override public void onSuccess(DataTransfer event) { assertNotNull(event); verify(eventBus).post(event); assertThat(event.getStatus(), is("OK")); assertTrue(event.getData() != null); testPassed[0] = true; } }; //Set our test EventBus object driver.setEventBus(eventBus); // The actual method under test driver.parseData(jsonParser.parse(json)); // Set a countdown latch to wait for the result (5s) latch.await(5000, TimeUnit.MILLISECONDS); // will wait here until 5s or the @Subscrube method is hit assertTrue(testPassed[0]); } //Because we want to examine EventBus Output, register it //to this class and pass the event back through our custom abstract class @Subscribe public void onReceiveEventBusEvent(DataTransfer event) { assertNotNull(transferCallback); transferCallback.onSuccess(event); //notify latch so that we can proceed latch.countDown(); } } 
+2
source

This does not work because instance not a layout. You will need to check the effects of callAMethod or put this method in another class and inject the layout of this new class into the ReceiverClass class.

For instance...

 private class ReceiverClass { private MyNewClass theNewClassIWasTalkingAbout; // Stick in a setter for that ^ @Subscribe public void onEventReceived(MyEvent myevent) { theNewClassIWasTalkingAbout.callAMethod(); } } 

Then your test will change a little ...

 @Mock private MyNewClass mockNewClass; @InjectMocks // This will be the "solid" implementation of the thing you are trying to test, it is not a mock... private ReceiverClass instance; @Test public void testBusReceivedEvent() { mockBus.register(instance); MyEvent myevent = new MyEvent(); mockBus.post(myevent); verify(mockNewClass, times(1)).callAMethod(); } 

Hope this helps.

0
source

All Articles