I am using Otto's event bus in my application. In one of my classes I am posting the event.
MyEvent myevent = new MyEvent();
uiBus.post(myEvent);
I am able to test the post method.
Now there is another class which is receiving the event.
//ReceiverClass.java
@Subscribe
public void onEventReceived(MyEvent myevent) {
callAMethod();
}
How do I unit test that this method was invoked. 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 doesn't work.
It does not work because instance
is not a mock. You will have to verify the effects of callAMethod
or put that method in another class and inject a mock of this new class into your ReceiverClass
class.
For example...
private class ReceiverClass {
private MyNewClass theNewClassIWasTalkingAbout;
// Stick in a setter for that ^
@Subscribe
public void onEventReceived(MyEvent myevent) {
theNewClassIWasTalkingAbout.callAMethod();
}
}
Then your test will have to change slightly...
@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.
I'm a little late to the party but here is an example of a class which works and accounts for async calls. Instead of Mocking EventBus we simply let it do it's thing and register it in the TestDriver
class below.
The thing that makes this work is the CountDownLatch
which, with the help of the abstract DataTransferCallback
class, waits for latch.countDown()
to be called or 5 seconds to go by.
Just register your test class and in the @Subscribe method, pass it back to the method that created the DataTransferCallback
and do your assertions 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();
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With