3

I have two microservices written with java vertx. They communicate via eventbus. First one sends a message and second receives the message.

First idea: Only reply to Vertx eventbus messages in unit test.

I want to test that message is being processed without errors and therefore I write unit test on second microservice that checks the reply

eventbus.send("address", message, reply -> {
    if (reply.succeeded()) {
        context.async().complete();
    } else {
        context.fail();
    }});

Now I have to send reply in my consumer, but I want to do it only in test, I do not need to send replies in production. I do not want to consume cpu and network to send replies in production. So what I am looking for is something like this:

vertx.eventBus().consumer("address", handler -> {
    Boolean success = methodMayFail();
    if ( MY_CONTEXT_IS_TEST || HANDLER_IS_LOCAL_AS_I_ONLY_SENT_LOCAL_MESSAGES_FROM_TEST) {
        success ? handler.reply("ok") : handler.fail();
    }
});

Second idea came after cdelmas comment and is in my own answer

Community
  • 1
  • 1
Anton Ivinskyi
  • 402
  • 5
  • 17

2 Answers2

2

To test async eventbus handler without reply you have to extract your business logic into service and split your test case into two. First for message passing, second for business logic.

ConsumerVerticle will look like this:

class ConsumerVerticle extends AbstractVerticle {
    // this service is injected somehow, for example as constructor parameter
    private MyService service;
    ...
    public void start() {
        vertx.eventBus().consumer("address", handler -> {
            service.methodMayFail();
        });
    }
}

In async test implement mock of your service with overridden method methodMayFail() that will hold the async

class MockService extends MyService() {
    private Async async;
    public MockService(Async async) {
        this.async = async;
    }
    @Override public void methodMayFail() {
        async.complete()
    }
}

And then inject the mock service into verticle

MockService service = new MockService(context.async()); 
ConsumerVerticle consumerVerticle = new ConsumerVerticle(service);
...
eventbus.send("address", message)

Somewhere in another class MyServiceTest test the implementation of methodMayFail().

Anton Ivinskyi
  • 402
  • 5
  • 17
0

It is a very bad practice to add code only for tests.

Although you don't reply, there is probably something you do in the consumer that can be checked, such as updating some state. This is what you should assert in your test, in my opinion.

cdelmas
  • 840
  • 8
  • 15
  • While I agree that adding code specifically for tests is a bad practice and you pointed me to right direction, this does not fully answer the question. The problem remains: how should I test async vertx eventbus handlers without sending reply. – Anton Ivinskyi Mar 28 '16 at 11:23