Creating stubs using the Hoverfly Java DSL

One of the things I like best about the option to write stubs for service virtualization in code is that by doing so, you’re able to store them in and access them through the same version control system (Git, for example) as your production code and your automated tests. I was excited when I read a blog post on the SpectoLabs website announcing that they had added a Java DSL to their most recent Hoverfly release. I’ve been keeping up with Hoverfly as a product for a while now, and it’s rapidly becoming an important player in the world of open source service virtualization solutions.

This Java DSL is somewhat similar to what WireMock offers, in that it allows you to quickly create stubs in your code, right when and where you need them. This blog post will not be a comparison between Hoverfly and WireMock, though. Both tools have some very useful features and have earned (and are stil earning) their respective place in the service virtualization space, so it’s up to you to see which of these best fits your project.

Instead, back to Hoverfly. Let’s take a look at a very basic stub definition first:

@ClassRule
public static HoverflyRule hoverflyRule = HoverflyRule.inSimulationMode(dsl(
   	service("www.afirststub.com")
       		.get("/test")
       		.willReturn(success("Success","text/plain"))
));

The syntax used to create a stub is pretty straightforward, as you can see. Here, we have defined a stub that listens at http://www.afirststub.com/test and returns a positive response, defined using the success() method, which boils down to Hoverfly returning an HTTP response with a 200 status code. The response further contains a response body with a string Success as its body and text/plain as its content type. By replacing these values with other content and content type values, you can easily create a stub that exerts the behaviour required for your specific testing needs.

As you can see, a Hoverfly stub is defined using the JUnit @ClassRule annotation. For those of you that use TestNG, you can manage the Hoverfly instance (the Hoverfly class is included in the hoverfly-java dependency) in @Before and @After classes instead.

We can check that this stub works as intended by writing and running a simple REST Assured test for it:

@Test
public void testAFirstStub() {
		
	given().
	when().
		get("http://www.afirststub.com/test").
	then().
		assertThat().
		statusCode(200).
	and().
		body(equalTo("Success"));
}

Since Hoverfly works as a proxy, it can return any data you specify, even for existing endpoints. This means that you don’t need to change existing configuration files and endpoints in your system under test when you’re running your tests, no matter whether you’re using an actual endpoint or the Hoverfly stub representation of it. A big advantage, if you ask me.

Consider the following (utterly useless) use case: the endpoint http://ergast.com/api/f1/drivers/max_verstappen.json returns data for the Formula 1 driver Max Verstappen in JSON format (you can click the link to see what data is returned). Assume we want to test what happens when the permanentNumber changes value from 33 to, say, 999, we can simply create a stub that listens at the same endpoint, but returns different data:

@ClassRule
public static HoverflyRule hoverflyRule = HoverflyRule.inSimulationMode(dsl(
       	service("ergast.com")
       		.get("/api/f1/drivers/max_verstappen.json")
       		.willReturn(success("{\"permanentNumber\": \"999\"}", "application/json"))
));

Note that I removed all other data that is returned by the original endpoint for brevity and laziness. Mostly laziness, actually. Again, a simple test shows that instead of the data returned by the real endpoint, we now get our data from the Hoverfly stub:

@Test
public void testStubFakeVerstappen() {
		
	given().
	when().
		get("http://ergast.com/api/f1/drivers/max_verstappen.json").
	then().
		assertThat().
		body("permanentNumber",equalTo("999"));
}

Apart from being quite useless, the example above also introduces an issue with defining stubs that return larger amounts of JSON data (or XML data, for that matter): since JSON is not really well supported out of the box in Java (nor is XML), we could potentially end up with a large and unwieldy string with lots of character escaping for larger response bodies. Luckily, Hoverfly offers a solution for that in the form of object (de-)serialization.

Assume we have a simple Car POJO with two fields: make and model. If we create an instance of that Car object like this:

private static Car myCar = new Car("Ford", "Focus");

and we pass this to the stub definition as follows:

@ClassRule
public static HoverflyRule hoverflyRule = HoverflyRule.inSimulationMode(dsl(
	service("www.testwithcarobject.com")
 		.get("/getmycar")
       		.willReturn(success(json(myCar)))
));

then Hoverfly will automatically serialize the Car object instance to JSON, which we can visualize by creating another REST Assured test and having it log the response body to the console:

@Test
public void testStubGetCarObject() {
		
	given().
	when().
		get("http://www.testwithcarobject.com/getmycar").
	then().
		log().
		body().
	and().
		assertThat().
		body("make",equalTo("Ford"));
}

When run, this test generates the following console output, indicating that Hoverfly successfully serialized our Car instance to JSON:

{
    "make": "Ford",
    "model": "Focus"
}

Note that the getters of the POJO need to be named correctly for this to work. For example, the getter for the make field needs to be called getMake(), or else the object will not be serialized.

The final Hoverfly feature that I’d like to demonstrate is the ability to simulate error flows by returning bad requests. This can be done simply as follows:

@ClassRule
public static HoverflyRule hoverflyRule = HoverflyRule.inSimulationMode(dsl(
       	service("www.badrequest.com")
       		.get("/req")
       		.willReturn(badRequest())
));

and can be verified by checking the status code corresponding with a bad request, which is HTTP 400, with a test:

@Test
public void testStubBadRequest() {
		
	given().
	when().
		get("http://www.badrequest.com/req").
	then().
		assertThat().
		statusCode(400);
}

Similar to the Hoverfly product in general, its Java DSL is still under construction. This post was written based on version 0.3.6 and does not reflect newer versions. I had a bit of trouble getting the code to run, initially, but the SpectoLabs team have been very responsive and helpful in resolving the questions I had and the issues I encountered.

As an end note, please be aware that the Java DSL we’ve seen in this post is just one way of using Hoverfly. For a complete overview of the features and possibilities provided by the tool, please take a look at the online documentation.

A Maven project featuring all of the examples and tests in this post can be downloaded here. Tip: you’ll need to set your Java compiler compliance level to 1.8 in order for the code to compile and run correctly.

Open sourcing my workshop on WireMock

For those of you that want to jump to the good stuff directly, you can find the workshop slides, exercises and everything related here.

A couple of weeks ago I was given the opportunity to deliver another workshop before TestNet, the Dutch software testing community, as part of their fall conference. Half a year ago, I did a similar workshop for their spring conference. That workshop was on RESTful API testing using REST Assured, which I decided to make open source a little later on. I’ve received some positive feedback on that, so why not do it again?

This time, the conference was centered around test automation. The subject of my workshop this time was closely related to the main theme: stubbing test environment dependencies using WireMock.

The title slide for my workshop

Delivery
As with most workshops that day, mine was set in a classroom-style space. I had somewhere between 15 and 20 participants, which I think is pretty much the ideal group size for a hands-on workshop that involves writing code. Not so many that I can’t give proper attention to all questions asked, but not a group so small you start to doubt whether the upfront investment has been worth it. As those of you who have prepared and delivered workshops before, you know that preparing them takes a lot of time. Spending all those hours and then only having two people turn up, one of whom is a coworker and the other one seems a little lost, is a bit of a bummer. Fortunately, this wasn’t the case for me, at least not this time..

The levels of experience of the participants (semi-pro tip: know your audience) ranged from people having some prior experience with stub and mock development to people that had never in their life written a single line of code before. An interesting mix, to say the least!

Workshop contents
As said, the main subject of the workshop was WireMock. I started out by telling people a little about the difficulties with regards to keeping test environments up and running and properly configured in these times of parallel development, Continuous Delivery and Testing and distributed applications. I then introduced WireMock, which I’ve done here on this site before as well. Then came four cycles of me presenting a WireMock feature, followed by exercises where the participants could try this feature out for themselves. I chose to highlight the following WireMock features in the workshop:

  • Writing a first, basic stub
  • Request matching options
  • Fault simulation
  • Creating stateful mocks

For each set of exercises, I prepared REST Assured tests that the participants could run to see if their stub implementation was correct. Call it test driven stub development if you like. This approach worked remarkably well, it definitely saved me a lot of time answering questions in the ‘is this correct?’ vein. Test green = stub good, test red = stub needs improvement. It doesn’t get any clearer than that.

Here’s an example of an exercise and the test that determines the correctness of the solution:

public void setupStubExercise101() {

	/************************************************
	 * Create a stub that listens at path
	 * /exercise101
	 * and responds to all GET requests with HTTP status code 200
	 ************************************************/
}

@Test
public void testExercise101() {
        
    wme.setupStubExercise101();
	         
    given().
    when().
        get("http://localhost:9876/exercise101").
    then().
        assertThat().
        statusCode(200);
}

How it turned out
Fine, I think. Time flew by and I didn’t experience any major faults, missing or incorrect slides or things like that. The experience I’m slowly gathering by doing this more often is starting to pay off, I think. I received almost exclusively positive feedback on the workshop, so I’m a happy guy. Also, everybody seemed to have learned at least something new and enjoyed the process too, no matter whether they had prior stubbing or even programming experience or not, and that has been the most important result of the morning to me. I’m looking forward to the next opportunity for delivering this workshop.

Having said that…
All workshop contents, that’s:

  • The complete set of slides
  • All workshop exercises and their answers
  • Matching REST Assured tests to verify the stubs created

can be found on my GitHub page. As with the previous workshop I’ve published in this manner, feel free to download, adapt, extend and then deliver the workshop to your liking. I look forward to hearing your experiences.

And in case you’re interested in following a WireMock workshop, but do not want to deliver this yourself, don’t hesitate to contact me. I’ll be happy to discuss options. Also, this workshop can easily be combined with a workshop on REST Assured for a full day of API testing and stubbing goodness.

(De)serializing POJOs in REST Assured

In this post, I’d like to demonstrate how you can leverage the ability of REST Assured to (de-)serialize Plain Old Java Objects (better known as POJOs) for more powerful testing.

As an example, we’ll use the following POJO representing a car and some of its properties:

public class Car {
	
	String make;
	String model;
	int year;
	
	public Car() {		
	}
	
	public Car(String make, String model, int year) {
		
		this.make = make;
		this.model = model;
		this.year = year;
	}
	
	public String getMake() {
		return this.make;
	}

	public void setMake(String make) {
		this.make = make;
	}
	
	public String toString() {
		return "My car is a " + this.year + " " + this.make + " " + this.model;
	}
}

Please note that I’ve removed the getters and setters for the other properties for brevity. Now, let’s create an instance of the car:

Car myCar = new Car("Aston Martin","DB9",2004);

Say we want to transmit the information stored in this object instance to a RESTful API, without having to map each individual property of our car to a corresponding field in the request. REST Assured supports this by allowing you to serialize the myCar object instance as follows:

@Test
public void testCarSerialization() {
				
	given().
		contentType("application/json").
		body(myCar).
	when().
		post("http://localhost:9876/carstub").
	then().
		assertThat().
		body(equalTo("Car has been stored"));
}

So, all you have to do is pass the object using body(). REST Assured will automatically translate this to the following request body:

{
    "make": "Aston Martin",
    "model": "DB9",
    "year": 2004
}

Neat, right? In this example, we serialized the car object to a JSON request, but REST Assured also allows you to serialize it to XML or HTML. Additionally, you can create custom object mappings as well. See this page in the REST Assured documentation for more information.

REST Assured also supports deserialization, meaning that we can easily transform a suitably formatted API response to a POJO instance:

@Test
public void testCarDeserialization() {
		
	Car myDeserializedCar = get("http://localhost:9876/carstub").as(Car.class);
		
	System.out.println(myDeserializedCar.toString());
	
	Assert.assertEquals("Check the car make", myDeserializedCar.getMake(), "Aston Martin");		
}

Note that http://localhost:9876/carstub points to a WireMock stub I’ve created to illustrate this example. The fact that our assertion is passing and that the console shows the following output when running the test tells us that deserialization has been successful:

My car is a 2004 Aston Martin DB9

You can download a Maven project containing all of the code I’ve used in the examples in this blog post here.