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.

Getting started with: WireMock

This is the seventh article in our series on new, popular or otherwise interesting tools used in test automation. You can read all posts within this series by clicking here.

What is WireMock?
From the WireMock.org website: WireMock is a flexible library for stubbing and mocking web services. Unlike general purpose mocking tools it works by creating an actual HTTP server that your code under test can connect to as it would a real web service. It supports HTTP response stubbing, request verification, proxy/intercept, record/playback of stubs and fault injection, and can be used from within a unit test or deployed into a test environment. Although it’s written in Java, there’s also a JSON API so you can use it with pretty much any language out there.

In short, WireMock is a very handy tool for all those situations where you need to set up a mock version of a web service, for example for testing or development purposes.

Where can I get WireMock?
WireMock can be downloaded from the WireMock Maven repository.

How do I install and configure WireMock?
Installing WireMock is as simple as downloading the latest standalone version from the WireMock Maven repository and adding it as a dependency to your Java project.

Creating a first WireMock mock service
Let’s start by creating a very simple mock service that returns a plain text string and a HTTP status code.

public void setupStub() {
		
	stubFor(get(urlEqualTo("/an/endpoint"))
            .willReturn(aResponse()
                .withHeader("Content-Type", "text/plain")
                .withStatus(200)
                .withBody("You've reached a valid WireMock endpoint")));
}

This code snippet creates a simple mock service that runs at the /an/endpoint endpoint on the WireMock server (your localhost most of the time, but more about that in a bit). It returns a response with content type text/plain, HTTP status 200 and body text “You’ve reached a valid WireMock endpoint“.

Running and testing your mock service
Of course, we would also like to validate whether the mock service we created does what we told it to do. In this post, I will use JUnit-based REST Assured tests to validate the behaviour of our mocks. But first, we need to get our mock service up and running before we start testing. This can be done very easily with WireMock using a JUnit @Rule:

@Rule
public WireMockRule wireMockRule = new WireMockRule(8090);

This rule starts and stops the mocks defined in your JUnit test class for every test in it. Next, we can define a couple of REST Assured tests to see whether the mock service is doing what we expect:

@Test
public void testStatusCodePositive() {
		
	setupStub();
		
	given().
	when().
		get("http://localhost:8090/an/endpoint").
	then().
		assertThat().statusCode(200);
}
	
@Test
public void testStatusCodeNegative() {
	
	setupStub();
		
	given().
	when().
		get("http://localhost:8090/another/endpoint").
	then().
		assertThat().statusCode(404);
}
	
@Test
public void testResponseContents() {
		
	setupStub();
	
	String response = get("http://localhost:8090/an/endpoint").asString();
	Assert.assertEquals("You've reached a valid WireMock endpoint", response);
}

When we run these tests, they will all pass, indicating our mock service behaves as expected:
WireMock JUnit test results

Request-response matching
WireMock also allows you to define a stub that returns a particular answer based on (part of) the request message using the matching matcher method:

public void setupStub() {
		
	stubFor(post(urlEqualTo("/pingpong"))
			.withRequestBody(matching("<input>PING</input>"))
            .willReturn(aResponse()
                .withStatus(200)
                .withHeader("Content-Type", "application/xml")
                .withBody("<output>PONG</output>")));
}

This service only returns a status code 200 and a response XML message when the request body equals a given value. Again, we can validate this easily using REST Assured:

@Test
public void testPingPongPositive() {
		
	setupStub();
		
	given().
		body("<input>PING</input>").
	when().
		post("http://localhost:8090/pingpong").
	then().
		assertThat().
		statusCode(200).
		and().
		assertThat().body("output", org.hamcrest.Matchers.equalTo("PONG"));
}

WireMock also allows you to use regular expressions for more flexible request matching.

Creating stateful mocks
As a final example, I’ll show how to create a stateful mock. This is done in WireMock using scenarios:

public void setupStub() {
		
	stubFor(get(urlEqualTo("/todolist"))
			.inScenario("addItem")
			.whenScenarioStateIs(Scenario.STARTED)
			.willReturn(aResponse()
                .withStatus(200)
                .withHeader("Content-Type", "application/xml")
                .withBody("<list>Empty</list>")));
		
	stubFor(post(urlEqualTo("/todolist"))
			.inScenario("addItem")
			.whenScenarioStateIs(Scenario.STARTED)
			.willSetStateTo("itemAdded")
			.willReturn(aResponse()
				.withHeader("Content-Type", "application/xml")
                .withStatus(201)));
		
	stubFor(get(urlEqualTo("/todolist"))
			.inScenario("addItem")
			.whenScenarioStateIs("itemAdded")
			.willReturn(aResponse()
                .withStatus(200)
                .withHeader("Content-Type", "application/xml")
                .withBody("<list><item>Item added to list</item></list>")));	
}

So, when we first perform a GET on this mock, an empty to-do list is returned. Then, when we do a POST, the mock service state is changed from Scenario.STARTED (a default in WireMock) to “itemAdded“. Then, when we do another GET, we get a to-do list with a single item on it:

@Test
public void testStatefulMock() {
		
	setupStub();
		
	given().
	when().
		get("http://localhost:8090/todolist").
	then().
		assertThat().
		statusCode(200).
		and().
		assertThat().body("list", org.hamcrest.Matchers.equalTo("Empty"));
		
	given().
	when().
		post("http://localhost:8090/todolist").
	then().
		assertThat().
		statusCode(201);
		
	given().
	when().
		get("http://localhost:8090/todolist").
	then().
		assertThat().
		statusCode(200).
		and().
		assertThat().body("list", org.hamcrest.Matchers.not("Empty")).
		and().
		assertThat().body("list.item", org.hamcrest.Matchers.equalTo("Item added to list"));
}

A trivial example, perhaps, but nevertheless it shows you how can create stateful mocks easily using WireMock.

Further reading
WireMock provides many more useful features for creating just the mock you want. A complete reference guide can be found on the WireMock website.

An Eclipse project including the mock services and REST Assured tests I’ve used in this post can be downloaded here.