Anton Ivinskyi
Anton Ivinskyi

Reputation: 392

How to test async vertx eventbus handlers without sending reply

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

Upvotes: 3

Views: 3273

Answers (2)

Anton Ivinskyi
Anton Ivinskyi

Reputation: 392

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().

Upvotes: 1

cdelmas
cdelmas

Reputation: 860

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.

Upvotes: 0

Related Questions