Testing Vert.x Applications With SpockFramework
TDD, BDD, and ATDD are all pretty popular methods of improving software quality and speeding delivery of software products in this day and age. Unit testing, via the likes of JUnit, has become the norm. Behavior testing, using tools like Cucumber or SpockFramework, have been gaining in popularity as they allow for more consumable and understandable tests while simplifying the test writing experience for developers and quality assurance personnel. Now let's tackle the challenge of bringing these tools to bare on our reactive applications.
Before we go too far though, I would like to say that if you can AVOID tests which require asynchronous interactions, you SHOULD. Whenever you have to write a test which relies on asynchronous operations, your tests get significantly more complex. In the Vert.x world, I highly recommend using method references so that you get very well isolated methods which do not rely on asynchronous operations; and thus those methods are VERY easy to test using whatever tool you like.
If you are not already familiar with Spock Framework, I highly recommend their documentation; which is very complete and pretty easy to navigate. The Javatar blog has an excellent tutorial to get you going with Spock as well. And while Spock makes use of the Groovy language, knowing Groovy is not really a prerequisite.
When you are looking to use Spock to test asynchronous code, the main thing you need to learn about is the AsyncConditions class. The AsyncConditions class is what allows Spock to handle asynchronous interactions without a lot of complex code to ensure that we get a result in a timely manner. Here's an example of what an AsyncConditions test might look like in Spock.
We could place additional assertions into the `async.evaluate` block to check for things like body content or required headers, but this is a perfectly reasonable basic test.
It is also possible that you would want to test a fairly complex set of interactions which might require several asynchronous operations to complete before the test is done. Let's expand our previous example to show how this can be accomplished.
You could potentially have any number of AsyncConditions which would need to be resolved, but the tests get more complex as you add more async operations.
I hope that this article has been as enjoyable to read as it was to write. Feel free to post below if you have any questions or need clarification!
Comments