Using Hamcrest Matchers with Vert.x Unit
Vert.x Unit is a very elegant library to test asynchronous applications developed with vert.x. However because of this asynchronous aspect, reporting test failures is not natural for JUnit users. This is because, the failed assertions need to be reported to the test context, controlling the execution (and so the outcome) of the test. In other words, in a Vert.x Unit test you cannot use the regular Junit assertions and assertion libraries. In this blog post, we propose a way to let you using Hamcrest matchers in Vert.x Unit tests.
Using Vert.x Unit
Vert.x Unit is a test library made to ensure the behavior of vert.x applications. It lets you implement tests checking asynchronous behavior.
Vert.x Unit can be used with Junit. For this, you just need to add the following dependency to your project:
If you are using Gradle, the dependency is:
If you are using an IDE, just add the vertx-unit jar to your project classpath.
Obviously, you would need to add JUnit too.
Notice that vertx-unit does not need JUnit, and can be used without it. Check the Vert.x Unit documentation for more details.
Vert.x Unit example
Let’s consider this very simple Verticle
:
It just creates a new HTTP server and when launched it notifies the future
of the completion.
To test this verticle with Vert.x Unit you would write something like:
First, the test class is annotated with @RunWith(VertxUnitRunner.class)
, instructing JUnit to use this special runner. This runner lets you inject a TestContext
parameter into every test methods (as well as @Before
and @After
) to handle the asynchronous aspect of the test.
In the setUp
method, it creates a new instance of Vertx
and deploy the verticle. Thanks to context.asyncAssertSuccess()
, it waits until the successful completion of the verticle deployment. Indeed, the deployment is asynchronous, and we must be sure that the verticle has been deployed and has completed its initialization before starting to test it.
The test()
method creates an Async
object that will be used to report when the test has been completed. Then it creates an HTTP client to emit a request on the server from our verticle and check that:
- the HTTP code is
200 (OK)
- the body is
hello vert.x
As you can see, to implement the checks, the assertions method are called on the TestContext
object, which control the test execution. When everything has been tested, we call async.complete()
to end the test. If an assertion failed, the test is obviously stopped. This would not be the case if you would use regular Junit assertions.
Using the Hamcrest Matchers
In the previous example, we used the the assertions available from the TestContext
instance. However it provides a limited set of methods. Hamcrest is a library of matchers, which can be combined in to create flexible expressions of intent in tests. It is very convenient when testing complex applications.
Hamcrest cannot be used directly as it would not report the failure on the TestContext
. For this purpose we create a VertxMatcherAssert
class:
This class provides assertThat
method that reports error on the given TestContext
. The complete code is available here.
With this class, we can re-implement our test as follows:
To ease the usage, I’ve added two import static:
You can use any Hamcrest matcher, or even implement your own as soon as you use the assertThat
method provided by VertxMatcherAssert
.
Conclusion
In this post we have seen how you can combine Hamcrest and Vert.x Unit. So, you are not limited anymore by the set of assert methods provided by Vert.x Unit, and can use the whole expressiveness of Hamcrest Matchers.
Don’t forget that you still can’t use the assert
methods from Junit, as they don’t report on the TestContext
.