0

I've already seen this SO question but yet it does not provide a solution to what I'm trying to do.

I'm using EventBus (from greenrobot) to send messages across my app. I'd like to be able to unit-test my app to confirm that a message have been posted to the bus. Just that.

Here's the class I'd like to test with a single method that post a message:

public class CxManager {
    public void postMessage(JsonObject data) {
        EventBus.getDefault().post(new MyCustomEvent(data));
    }
}

And here's the test I've tried but does not work:

@RunWith(MockitoJUnitRunner.class)
public class CxManagerTest {

    @Mock EventBus eventBus;
    private CxManager cxManager;
    private JsonObject testJsonObject;

    @Before public void setUp() throws Exception {
        cxManager = new CxManager();

        testJsonObject = new JsonObject();
        testJsonObject.addProperty("test", "nada");
    }

    @Test public void shouldPass() {
        cxManager.postMessage(testJsonObject);

        verify(eventBus).post(new MyCustomEvent(testJsonObject));
    }
}

I've written this test even knowing that it was likely to fail because EventBus uses a Singleton to post messages and I don't know how to test a singleton method being executed.

Also, this is just a piece of a large project. The relevant pieces. And I'd like to test the correct posting of messages according to different interactions

sebasira
  • 1,739
  • 1
  • 22
  • 41

1 Answers1

2

Your problem is that the event bus the CxManager is posting to isn't your mock object. You'd have to reorganize your code to pass the EventBus into CxManager, either directly or via dependency injection, so that it posts to that eventBus rather than however its getting one now.

Alternatively, get an instance of the EventBus its actually posting to, and subscribe to it. THere's no need to actually mock EventBus here.

Gabe Sechan
  • 90,003
  • 9
  • 87
  • 127
  • thanks! So one way to go is passing the EventBus to the CxManager constructor. I'll try that. I didn't get the last part *"get an instance of the EventBus its actually posting to, and subscribe to it"* could you explain? – sebasira Sep 10 '18 at 12:37
  • The cx manager is (or should be at least) getting an actual event bus from somewhere and is posting to that. If you could get that, you could just subscribe to it. A mock isn't really needed here – Gabe Sechan Sep 10 '18 at 12:40
  • Ohh I think I get it... but don't know exactly how to implement it. You want me to subscribe to the same event I'm posting so if I receive the message is because it was posted, right? That seems an interesting way, and was my first attempt. But the guidelines I've followed where confusing and complicated. Can you edit your answer and show me how to achieve it? I'm also accepting your solution because even with the first part of your answer I can solve my problem, but I'd like to try the second part as you suggest, without a mock – sebasira Sep 10 '18 at 12:43
  • 1
    No, I want you to subscribe to the same bus. An event bus isn't a global thing all events go to. You can create as many bus instances as you wish. Somewhere, cx manager is creating one, or grabbing one from somewhere. If you subscribed to that same instance, you wouldn't need to mock anything. You could test and see if the actual function was called. Either way works, it depends on what's easier. – Gabe Sechan Sep 10 '18 at 12:47
  • Alright! Thanks again! I thought the EventBus was **THE** EventBus and was all manage by a singleton instance. Thanks for clarification. – sebasira Sep 10 '18 at 12:53
  • That's a common way to use it, but in that case there will be a singleton event bus in your code somewhere.the library doesn't enforce it – Gabe Sechan Sep 10 '18 at 13:07