Yannic Bürgmann
Yannic Bürgmann

Reputation: 6581

Vert.x Unit Test a Verticle that does not implement the start method with future

I'm new to Vert.x and just stumbled about a problem. I've the following Verticle:

public class HelloVerticle extends AbstractVerticle {

  @Override
  public void start() throws Exception {

    String greetingName = config().getString("greetingName", "Welt");
    String greetingNameEnv = System.getenv("GREETING_NAME");
    String greetingNameProp = System.getProperty("greetingName");

    Router router = Router.router(vertx);
    router.get("/hska").handler(routingContext -> {
        routingContext.response().end(String.format("Hallo %s!", greetingName));
    });
    router.get().handler(routingContext -> {
        routingContext.response().end("Hallo Welt");
    });

    vertx
            .createHttpServer()
            .requestHandler(router::accept)
            .listen(8080);
  }
}

I want to unit test this verticle but i dont know how to wait for the verticle to be deployed.

@Before
public void setup(TestContext context) throws InterruptedException {
    vertx = Vertx.vertx();
    JsonObject config = new JsonObject().put("greetingName", "Unit Test");

    vertx.deployVerticle(HelloVerticle.class.getName(), new DeploymentOptions().setConfig(config));
}

when i setup my test like this i have to add a Thread.sleep after the deploy call, to make the tests be executed after some time of watiting for the verticle.

I heared about Awaitability and that it should be possible to wait for the verticle to be deployed with this library. But I didn't find any examples of how to use Awaitability with vertx-unit and the deployVerticle method.

Could anyone bring some light into this?

Or do i really have to hardcode a sleep timer after calling the deployVerticle-Method in my tests?

Have a look into the comments of the accepted answer

Upvotes: 0

Views: 1760

Answers (1)

alexvetter
alexvetter

Reputation: 1996

First of all you need to implement start(Future future) instead of just start(). Then you need to add a callback handler (Handler<AsyncResult<HttpServer>> listenHandler) to the listen(...) call — which then resolves the Future you got via start(Future future).

Vert.x is highly asynchronous — and so is the start of an Vert.x HTTP server. In your case, the Verticle would be fully functional when the HTTP server is successfully started. Therefore, you need implement the stuff I mentioned above.

Second you need to tell the TestContext that the asynchronous deployment of your Verticle is done. This can be done via another callback handler (Handler<AsyncResult<String>> completionHandler). Here is blog post shows how to do that. The deployment of a Verticle is always asynchronous even if you implemented the plain start() method. So you should always use a completionHandler if you want to be sure that your Verticle was successfully deployed before test.

So, no you don't need to and you definitely shouldn't hardcode a sleep timer in any of your Vert.x applications. Mind The Golden Rule - Don’t Block the Event Loop.

Edit:

If the initialisation of your Verticle is synchronous you should overwrite the plain start() method — like it's mentioned in the docs:

If your verticle does a simple, synchronous start-up then override this method and put your start-up code in there.

If the initialisation of your Verticle is asynchronous (e.g. deploying a Vert.x HTTP server) you should overwrite start(Future future) and complete the Future when your asynchronous initialisation is finished.

Upvotes: 1

Related Questions