Skip to content

Start with vertx-junit5 at no time

Hello, world! In this tutorial I would like to talk a bit about vertx-junit5. Don’t confuse it with more known vertx-unit library. This is a JUnit5-specific extension that you could use in order to simplify testing of Vert.x applications. And to make it more JUnit5-native.

Basic test structure

vertx-junit5 follows JUnit5’s extension model. Once you extend your test class with VertxExtension, you can use common JUnit 5 test structure:

//extension
@ExtendWith(VertxExtension.class)
class SampleTest{

//execute before each test
@BeforeEach
void before(Vertx vertx, VertxTestContext context){
	System.out.println("Before");
	vertx.deployVerticle(new SampleVerticle(), context.completing());
}

@Test
void test(Vertx vertx, VertxTestContext context){
	System.out.println("Test");
	//assertions...
}

//execute after each test
@AfterEach
void after(Vertx vertx, VertxTestContext context){
	System.out.println("After");
}
}

Note, that vertx-junit5 injects Vertx and VertxTestContext instances to methods, but this is optional. You can create these instances manually. There are some rules regarding Vertx instance lifecycle:

  1. Instance created in @BeforeAll is used throughout whole test
  2. Instance created in @BeforeEach is used inside respective test method and until @AfterEach
  3. Instance created in @Test is used in the respective test method’s scope only.

More on Vertx lifecycle is in docs.

Helper methods

You can use any assertions framework with vertx-junit5, as well standard JUnit5 assertions as well. There are several handy constructions you could use to test asynchronous Vertx code:

Verify()

VertxTestContext offers us verify() method. You should pass a block of code with assertions and any exception that would be thrown inside that code block fails test. Take a look on example:

int value = 4;

context.verify(()->{
	Assertions.assertEquals(5, value);
	context.completeNow();
});

By the way, pay attention, that you need to complete VertxTestContext. To notify about failure there is also failNow method.

Completing()

This method creates an asynchronous result handler that expects a success to then complete the test context. Optionally, you can pass the result of handler to an another callback.

context.succeeding(res->context.verify(()->{
	Assertions.assertTrue(true);
	context.completeNow();
}));

Failing()

This method creates an asynchronous result handler that expects a failure. Optionally, you can pass an exception to another callback.

context.failing(res->context.verify(()->{
	Assertions.assertEquals(5,4);
	context.completeNow();
}));

How to use checkpoints

Vertx framework brings the concept of checkpoints. Checkpoint represents a test completion stage, and flagging it advances towards the test context completion. When all checkpoints have been flagged, then VertxTestContext makes test pass. For instance, you can flag several steps: creation of server, request sending, response handling:

So, if you want to assure that your code passes several required steps, you can add checkpoints to your test. Take a look on the code snippet below (and by the way I use Java 11 HttpClient in this code):

Checkpoint serverCheckpoint = context.checkpoint();

/* pass 5 as argument to flag checkpoints 5 times */
Checkpoint requestCheckpoint = context.checkpoint(5);
Checkpoint responseCheckpoint = context.checkpoint(5);

//create server
vertx.createHttpServer().requestHandler(req->{
	req.response().end("Hello server");
	//send response
	responseCheckpoint.flag();
}).listen(4567, res->{
	if (r.succeded()){
		//server created
		serverCheckpoint.flag();
	} else {
		//something wrong
		context.failNow(res.cause());
	}
});

//send request

//send 5 times
for (int i=0; i<5; i++){
	var res = client.send(request, HttpResponse.BodyHandlers.ofString());
	String body = res.body();
	if (body.equalsIgnoreCase("Hello server")){
		requestCheckpoint.flag();
	} else {
		context.failNow(new Exception());
	}
}

Conclusion

In this short tutorial, I observed important components you need to start with vertx-junit5 library. It is not scary, and if you are experienced with Vertx and JUnit 5 frameworks already, you would get this at no time.

References

  • Julien Ponge. JUnit 5 support lands in Eclipse Vert.x for testing asynchronous operations (2018). Red Hat Developer, read here