Spring Boot 1.4: Gherkin tests

In this post I show how you can implement Gherkin tests for Spring Boot 1.4.1. Here is an example of a Gherkin based test script:

The Feature, Scenario, Scenario Outline, Given, When, Then and And constructs are part of the Gherkin test language [1]. Such tests are popular in Behavior-driven development (BDD) and is meant as a common tool between users from the business and users from the development team [2].

The idea is that you can execute such a Gherkin script and get a test result (did it work or not?)

Notice the Gherkin language, there is nothing that prevents you from writing such tests even before the real business code exists. In fact it is a BDD best practice to write the tests before the feature gets implemented:

Imagine if you and the business wrote Gherkin tests as part of a User Story’s acceptance criteria…

I haven’t done this yet. But I bet there are a lot of BDD practitioners that have.

About the Spring Boot 1.4 example

I have prepared a Spring Boot 1.4.1 based example on GitHub. Consult that to see the code in its entirety and true surroundings. The example consists of:

The Gherkin test script you saw at the beginning of this post: It’s a script that tests a “greetings” RESTful(ish) resource.

The greetings resource: A super simple Spring MVC @RestController that accepts a caller name as input and emits a greeting message as output. This is the resource being tested.

Notice the comments in the buildscript. They highlight what parts of the Gradle script are particularly interesting.

By using the Gradle Cucumber Plugin you now have the support for a new source folder structure:

src/cucumber
|--- java
|--- resources

You put the Gherkin step implementations in the src/cucumber/java directory and the Gherkin scripts under the src/cucumber/resources directory.

Step 2 of 5: Write the Gherkin tests

The Gherkin tests are written in a .feature file. In the example I put the following contents into src/cucumber/resources/greetingsResource.feature:

This script contains 3 test scenarios.

The two first tests are based on the Scenario Outline and uses data from the Examples block. First column is the input we send to the greetings resource. Second and third columns are the expected outputs given that input. So: If we send in Duke to the greetings resource then we expect an HTTP status code 200 and a body with the message Hello World, Duke.

The third test is a Scenario that is not based on example input data. This test is just for fun 😉 [5].

In the real world you would cover error conditions as well. So if you are testing a RESTful resource, like in this example, you would test for client errors 4xx etc.

Take a look at the class definition: this is where we tell the cucumber test framework to kickstart the Spring container. In fact it’s just like you would do in a typical Spring Boot 1.4 integration test: using the @SpringBootTest annotation. Said in another way: The Spring ApplicationContext will be launched prior to executing the Gherkin test scenarios.

Now take a look at lines 5+6: Here we inject Springs TestRestTemplate. We use this to send HTTP requests for our RESTful resource. Again, this is just like you would do in a typical Spring Boot 1.4 integration test.

Now take a look at the @Given, @When, @Then, and @And annotations: These define the methods implementing the steps. You can track them right back to the src/cucumber/resources/greetingsResource.feature file. Notice how we use simple regular expressions to map step input (fx caller values) to method parameters.

See? It almost looks like a normal Spring Boot integration test. One major difference is the need for storing intermediate state in the class itself (or somewhere else: fx a shared class). Well rest in the knowledge that any involved step classes, here GreetingsResourceSteps, are disposed after each Scenario. Said in another way: you have a fresh “steps” instance for each scenario.

You may also want to take a look at the @Before and @After cucumber annotations. They resemble the same from JUnit.

Step 4 of 5: Implement the feature being tested

Lastly, we get to the actual feature. It’s just the ordinary @RestController: