In this tutorial, I will explain how to create a standalone WireMock stub server for stubbing APIs. We will use, WireMock and JAVA for this stub setup. Creating a standalone stub server is one of the important parts of API test automation. We need to create stubs or mocks when the API under test is not completely ready or we need to test the external systems without getting affected by any external environmental problems. We are also getting much faster responses from the stubs/mocks rather than real implementations that run in an environment.
First, I will define our API requirements. We will define a shopping cart API swtestacademyshop.com and then start to create a stub for this API. In another article, we will create an API Test Automation Framework with Rest Assured to test this API by running our Standalone stub server. We will create a stub project separately in this article but if you want, you can also combine them in one project.
Note: swtestacademyshop.com is an artificial website, it is not a real website.
This article’s focus is the create a standalone stub server with Wiremock for swtestacademyshop’s shopping cart API. Let’s start with defining our sample service which is a shopping cart service for swtestacademyshop.com. After shopping cart API design, we will start to create our WireMock stub server project step by step.
Design a Sample Service and Define Requirements
Now, let’s wear a solution designer/analyst hat and define our API requirements and design. Our service has all the below specifications.
- Endpoint URL (Base path and resource path)
- Body
- Query Parameters
- Path Parameters
- Headers
Generally, services have the above components. Some of them have them all, some of them haven’t. Our service has all of them. On swtestacademyshop, we will sell courses. Our product type is courses and we can do below operations for shoppingcart service:
- Create a shopping cart. (POST)
- Get/Retrieve shopping cart details. (GET)
- Add a course to the shopping cart. (POST)
- Update a course in the shopping cart. (PUT)
- Delete a course from the shopping cart. (DELETE)
- Delete all shopping carts. (DELETE)
Now let’s define the service requirements step by step.
Service URL
Base URL | http://test.swtestacademyshop.com |
Base Path | carts |
Create a Shopping Cart
Method: POST
Resource Path: No resource path required.
Example Request: POST /carts
Body:
I defined a very basic simple shopping cart body as shown below.
This article is not a comprehensive API design article thus I don’t want to go into too much detail and I don’t want to write all min, max, mandatoriness requirements of each field.
Our shopping cart has customer and products attributes and they have their own attributes as shown below.
{ "customer":{ "id":"872738729", "firstName":"Onur", "lastName":"Baskirt", "email":"onur.baskirt@" }, "products":[ { "description":"Rest Api Testing with Rest Assured and Spring.", "type":"Course", "productAttributes":[ { "courseLenght":"5 hours", "courseCreationDate":"2021-01-14", "courseLevel":"Advanced" } ], "price":{ "amount": 80.0, "discount": 30.0, "paymetType":"CREDIT CARD", "currency": "USD" } } ] }
Also, you can use http://jsonviewer.stack.hu/ to see JSON documents nicer.
Headers:
Content-Type | application/json |
Accept | application/json |
Version | v1 |
Client | Android |
Authorization | Bearer <token> |
We do not have any path or query parameters for creating a cart operation.
Response:
Below is our sample create cart response. It contains only one course and as you see below, we have shoppingCartId and productId attributes.
HTTP Status Code: 201 CREATED
{ "id": "klms2f4c-8129-4a4b-b32d-550b7fc3cfb2", "customer": { "id": "872738729", "firstName": "Onur", "lastName": "Baskirt", "email": "onur.baskirt@" }, "products": [ { "id": "93b55282-334c-48b0-a8f7-a9d5eef9c4b9", "description": "Rest Api Testing with Rest Assured and Spring.", "type": "Course", "productAttributes": [ { "courseLenght": "5 hours", "courseCreationDate": "2021-01-14", "courseLevel": "advanced" } ], "price": { "amount": 80.0, "discount": 30.0, "paymetType": "CREDIT CARD", "currency": "USD" } } ] }
Get a Shopping Cart
Method: GET
Resource Path: {cartId}
Query Param: productCount (I added to distinguish 1 and 2 product mocking. Normally, we do not need this kind of QueryParams.)
Example Request: GET /carts/klms2f4c-8129-4a4b-b32d-550b7fc3cfb2?productCount=1
Response:
HTTP Status Code: 200 OK
{ "id": "klms2f4c-8129-4a4b-b32d-550b7fc3cfb2", "customer": { "id": "872738729", "firstName": "Onur", "lastName": "Baskirt", "email": "onur.baskirt@" }, "products": [ { "id": "93b55282-334c-48b0-a8f7-a9d5eef9c4b9", "description": "Rest Api Testing with Rest Assured and Spring.", "type": "Course", "productAttributes": [ { "courseLenght": "5 hours", "courseCreationDate": "2021-01-14", "courseLevel": "advanced" } ], "price": { "amount": 80.0, "discount": 30.0, "paymetType": "CREDIT CARD", "currency": "USD" } } ] }
Add a Product to Shopping Cart
Method: POST
Resource Path: {cartId}/products
Body:
{ "products": [ { "description": "Selenium Webdriver Tutorial.", "type": "Course", "productAttributes": [ { "courseLenght": "4 hours", "courseCreationDate": "2020-08-15", "courseLevel": "intermediate" } ], "price": { "amount": 60.0, "discount": 20.0, "paymetType": "CREDIT CARD", "currency": "USD" } } ] }
Example Request: POST /carts/klms2f4c-8129-4a4b-b32d-550b7fc3cfb2/products
Response:
HTTP Status Code: 201 CREATED
{ "products": [ { "id": "94b55282-334c-48b0-a8f7-a9d5eef9c4c9", "description": "Selenium Webdriver Tutorial.", "type": "Course", "productAttributes": [ { "courseLenght": "4 hours", "courseCreationDate": "2020-08-15", "courseLevel": "intermediate" } ], "price": { "amount": 60.0, "discount": 20.0, "paymetType": "CREDIT CARD", "currency": "USD" } } ] }
Update a Product to Shopping Cart
Method: PUT
Resource Path: {cartId}/products/{productId}
Example Request: PUT /carts/klms2f4c-8129-4a4b-b32d-550b7fc3cfb2/products/93b55282-334c-48b0-a8f7-a9d5eef9c4b9
Body:
{ "description": "Rest Api Testing with Rest Assured and Spring.", "type": "Course", "productAttributes": [ { "courseLenght": "5 hours", "courseCreationDate": "2021-01-14", "courseLevel": "advanced" } ], "price": { "amount": 91.42, "discount": 20.0, "paymetType": "CREDIT CARD", "currency": "USD" } }
Response:
HTTP Status Code: 200 OK
{ "id": "93b55282-334c-48b0-a8f7-a9d5eef9c4b9", "description": "Rest Api Testing with Rest Assured and Spring.", "type": "Course", "productAttributes": [ { "courseLenght": "5 hours", "courseCreationDate": "2021-01-14", "courseLevel": "advanced" } ], "price": { "amount": 91.42, "discount": 20.0, "paymetType": "CREDIT CARD", "currency": "USD" } }
Delete a Product from Shopping Cart
Method: DELETE
Resource Path: {cartId}/products/{productId}
Example Request: DELETE /carts/klms2f4c-8129-4a4b-b32d-550b7fc3cfb2/products/93b55282-334c-48b0-a8f7-a9d5eef9c4b9
Body: No Body!
Response:
HTTP Status Code: 204 NO CONTENT
Delete Shopping Cart
Method: DELETE
Resource Path: {cartId}
Example Request: DELETE /carts/klms2f4c-8129-4a4b-b32d-550b7fc3cfb2
Body: No Body!
Response:
HTTP Status Code: 204 NO CONTENT
Standalone WireMock Stub Server Creation
Now, we can create a stub server based on our requirements. These requirements are just a sample and not production level requirements. We are just trying to learn how to use wire mock that’s why please do not stick the design and requirements part so much.
Based on the requirements of the swtestacademy shopping cart service, we can start our project.
Step-1: Add Required Dependencies to pom.xml
Please use recent libraries. When I am writing this article, I used the recent ones in this pom.xml.
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>swtestacademyshopstub</artifactId> <version>1.0-SNAPSHOT</version> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>8</source> <target>8</target> </configuration> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>com.github.tomakehurst</groupId> <artifactId>wiremock</artifactId> <version>2.25.1</version> </dependency> <dependency> <groupId>org.json</groupId> <artifactId>json</artifactId> <version>20190722</version> </dependency> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.8.6</version> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>5.5.2</version> </dependency> </dependencies> </project>
Step-2: Create Mock JSON Files
For each operation CREATE, ADD, UPDATE, etc. we should create sample request and response files based on the requirements and we need to locate them under:
test -> resources -> __files package. I also added an extra one more package as JSON but it is not necessary because we are creating a stub server for REST API with JSON. We do not have any XML communication.
I don’t want to copy and paste all JSON files here. You can check them in GitHub link.
Step-3: Coding the Stub Server
The structure of the code is not complex. I want to create a stub server as simply as possible. We have one util class for JSON operations, one main class, and one stub class for building/creating the stubs. Also, you can add some controller classes to make this stub server more intelligent. In this article, I do not want to share too much complexity.
Also, you have to know how to deal with pattern matching for both URLs and Bodies. For this, please check official Wiremock documentation. They shared many examples. Here is the link: http://wiremock.org/docs/request-matching/
Let’s start with JsonUtil class.
JsonUtil.java
This class does a very basic JSON read operation. We will use setJSON and getJSON methods in our stub creation methods.
package utils; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; import org.json.JSONObject; import org.json.JSONTokener; public class JsonUtil{ public JSONObject jsonObject; private File jsonFile; public JSONObject getJSON() { return jsonObject; } public JsonUtil setJSON(String path) { jsonFile = new File(System.getProperty("user.dir") + "/src/test/resources/" + path); jsonObject = readJSONAsJSONObject(); return this; } public JSONObject readJSONAsJSONObject() { InputStream is = null; try { is = new FileInputStream(jsonFile); } catch (FileNotFoundException e) { e.printStackTrace(); } JSONTokener jsonTokener = new JSONTokener(is); jsonObject = new JSONObject(jsonTokener); return jsonObject; } }
Stubs.java
In this class, we will create our mocks. Based on Wiremock functionalities, we will use different approaches to create these mocks. Please, try to understand the below code by yourself and also check wiremock documentation. If you have questions, pleae post a comment. I will do my best to reply to your questions.
import com.github.tomakehurst.wiremock.WireMockServer; import utils.JsonUtil; import static com.github.tomakehurst.wiremock.client.WireMock.*; public class Stubs { private JsonUtil jsonUtil; public WireMockServer wireMockServer; public Stubs setUp() { wireMockServer = new WireMockServer(3467); wireMockServer.start(); jsonUtil = new JsonUtil(); return this; } public Stubs resetServer() { wireMockServer.resetAll(); return this; } public Stubs stubForCreateCart(String responseFileName) { wireMockServer.stubFor(post("/carts") .withHeader("Content-Type", equalToIgnoreCase("application/json")) .withHeader("Accept", equalToIgnoreCase("application/json")) .withHeader("Version", equalToIgnoreCase("v1")) .withHeader("Client", equalToIgnoreCase("Android")) .withHeader("Authorization", equalToIgnoreCase("Bearer SWTestAcademyShopSecretToken")) .withRequestBody(matchingJsonPath("$.customer.firstName", equalTo("Onur"))) .withRequestBody(matchingJsonPath("$.customer.lastName", equalTo("Baskirt"))) .willReturn(aResponse() .withStatus(201) .withHeader("Content-Type", "application/json") .withBodyFile("json/" + responseFileName))); return this; } public Stubs stubForCreateCartError(String responseFileName) { wireMockServer.stubFor(post("/carts") .withHeader("Authorization", equalToIgnoreCase("Bearer Error")) .willReturn(aResponse() .withStatus(401) .withHeader("Content-Type", "application/json") .withBodyFile("json/" + responseFileName))); return this; } public Stubs stubForGetCartSingle(String responseFileName) { wireMockServer.stubFor(get("/carts/klms2f4c-8129-4a4b-b32d-550b7fc3cfb2?productCount=1") .willReturn(aResponse() .withStatus(200) .withHeader("Content-Type", "application/json") .withBodyFile("json/" + responseFileName))); return this; } public Stubs stubForGetCartDouble(String responseFileName) { wireMockServer.stubFor(get("/carts/klms2f4c-8129-4a4b-b32d-550b7fc3cfb2?productCount=2") .willReturn(aResponse() .withStatus(200) .withHeader("Content-Type", "application/json") .withBodyFile("json/" + responseFileName))); return this; } public Stubs stubForAddProduct(String requestFileName, String responseFileName) { jsonUtil.setJSON("/__files/json/".concat(requestFileName)); wireMockServer.stubFor(post("/carts/klms2f4c-8129-4a4b-b32d-550b7fc3cfb2") .withRequestBody(equalToJson(jsonUtil.getJSON().toString(), true, true)) .willReturn(aResponse() .withStatus(200) .withHeader("Content-Type", "application/json") .withBodyFile("json/" + responseFileName))); return this; } public Stubs stubForPutProduct(String requestFileName, String responseFileName) { jsonUtil.setJSON("/__files/json/".concat(requestFileName)); wireMockServer.stubFor(post("/carts/klms2f4c-8129-4a4b-b32d-550b7fc3cfb2/products/93b55282-334c-48b0-a8f7-a9d5eef9c4b9") .withRequestBody(equalToJson(jsonUtil.getJSON().toString(), true, true)) .willReturn(aResponse() .withStatus(200) .withHeader("Content-Type", "application/json") .withBodyFile("json/" + responseFileName))); return this; } public Stubs stubForDeleteProduct() { wireMockServer.stubFor(delete("/carts/klms2f4c-8129-4a4b-b32d-550b7fc3cfb2/products/93b55282-334c-48b0-a8f7-a9d5eef9c4b9") .willReturn(aResponse() .withStatus(204))); return this; } public Stubs stubForDeleteCart() { wireMockServer.stubFor(delete("/carts/klms2f4c-8129-4a4b-b32d-550b7fc3cfb2") .willReturn(aResponse() .withStatus(204))); return this; } public Stubs status() { System.out.println("Stubs Started!"); return this; } }
StubServerMain.java
We will chain our stub creation methods in the main class. :) That’s all we do in this class.
public class StubServerMain { public static Stubs stubs = new Stubs(); public static void main(String[] args) { stubs.setUp() .stubForCreateCart("CreateCartSuccessResponse.json") .stubForCreateCartError("CreateCartErrorResponse.json") .stubForGetCartSingle("CreateCartSuccessResponse.json") .stubForGetCartDouble("GetCartDoubleResponse.json") .stubForAddProduct("AddProductRequest.json","AddProductResponse.json") .stubForPutProduct("PutProductRequest.json","PutProductResponse.json") .stubForDeleteProduct() .stubForDeleteCart() .status(); } }
After all of these steps, you should run and test your stub server.
First, create an application run in the run panel of IntelliJ.
Then run it.
And then open the PostMan and test the stub server as shown below.
GitHub URL: https://github.com/swtestacademy/wiremock-stub-server
Postman Collection: https://www.getpostman.com/collections/f1e6e53de1f2ab77a6d1
Thanks.
Onur

Onur Baskirt is a Software Engineering Leader with international experience in world-class companies. Now, he is a Software Engineering Lead at Emirates Airlines in Dubai.
Hey Onur,
Thanks for sharing this work made my day! I slightly changed the context and added a pattern that helps segregating multiple service class layers.
github.com/ozinal/wiremock-stub-server
Bayram
Thanks a lot, Bayram. It looks really nice solution.
Hi Onur,
I see stubs.java returning the response. Any way we can convert the response to Pojo ( MyResponse ) class ?
Yes sure, you can do it by using “jackson-databind” library.
Below I am sharing a sample code.
Supplier OBJECT_MAPPER = () -> {
final ObjectMapper mapper = new ObjectMapperConfigurer(new ObjectMapper()).getObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, true);
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
return mapper;
};
/**
* This method getObjectFromJson will return jsonAsObject.
*
* @param json input parameter
* @param type input parameter
* @return jsonAsObjectFromString
*/
static < T > T getObjectFromJson(final String json, final Class< T > type) {
try {
return OBJECT_MAPPER
.get()
.readValue(json, type);
} catch (final IOException e) {
throw new IllegalStateException(e);
}
}
i need to use wiremockServer without wiremock jar. i need it in java code.
can you please help here .
please share the code snippet
Add this in your pom.xml: https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-contract-wiremock/3.0.4
Use this annotation on top of your test class: @AutoConfigureWireMock(port = 6536)
Then, create your mocks like below:
stubFor(get(“/my_api/my_resource/v1”)
.willReturn(
aResponse()
.withStatus(200)
.withHeader(“Content-Type”, “application/json”)
.withHeader(“Accept”, “application/json”)
.withBodyFile(responseFileName)));
Hi Ankur,
Great article, thanks. A query below..
In the stubForPutProduct, shouldn’t the stub creation be stubFor(put(.. instead of subtFor(post(..
public Stubs stubForPutProduct(String requestFileName, String responseFileName) {
jsonUtil.setJSON(“/__files/json/”.concat(requestFileName));
wireMockServer.stubFor(post(“/carts/klms2f4c-8129-4a4b-b32d-550b7fc3cfb2/products/93b55282-334c-48b0-a8f7-a9d5eef9c4b9”)
.withRequestBody(equalToJson(jsonUtil.getJSON().toString(), true, true))
.willReturn(aResponse()
.withStatus(200)
.withHeader(“Content-Type”, “application/json”)
.withBodyFile(“json/” + responseFileName)));
return this;
}
……