Thursday, 14 May 2020

WireMock: Generate dynamic http responses using Response Templates

How to enable Response Templating?

By adding ResponseTemplateTransformer as an extension, you can enable Response Templating.

 

Example

WireMockRule wireMockRule = new WireMockRule(WireMockConfiguration.options().extensions(new ResponseTemplateTransformer(true)));

 

As you see the constructor of ResponseTemplateTransformer, it takes a boolean argument. If the boolean argument is true, then the extension should be applied globally and all stub mapping responses will be rendered as templates prior to being served.

 

For example, for the request ‘/api/v1/employees/3’

 

request.path.[0] refers to api
request.path.[1] refers to v1
request.path.[2] refers to employees
request.path.[3] refers to 3

 

Following example defines template file that dynamically update employee id from the request path before sending the response from wiremock.

 

Step 1: Get an instance of WireMockRule using ResponseTemplateTransformer.

 

@Rule
public WireMockRule wireMockRule = new WireMockRule(WireMockConfiguration.options().port(HTTP_SERVICE_PORT).httpsPort(HTTPS_SERVICE_PORT).notifier(new ConsoleNotifier(true)).extensions(new ResponseTemplateTransformer(true)));
 

Step 2: Create 'employeeByIdTemplate.json' file in 'src/test/resources/__files' folder.

 

employeeByIdTemplate.json

{
         "id": "{{request.path.[3]}}",
         "firstName": "Ram",
         "lastName": "Ponnam"
}

 

As you see ‘request.path.[3]’ is mentioned between {{ }}.

 

Step 3: Serve the response from employeeByIdTemplate.json file.

wireMockRule.stubFor(get(urlPathMatching("/api/v1/employees/3")).willReturn(aResponse().withStatus(200).withHeader("Content-Type", "application/json").withBodyFile("employeeByIdTemplate.json")));

 

Find the below working application.

 

Employee.java

package com.sample.app.model;

public class Employee {

	private int id;
	private String firstName;
	private String lastName;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getFirstName() {
		return firstName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	public String getLastName() {
		return lastName;
	}

	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	@Override
	public String toString() {
		return "Employee [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + "]";
	}

}

EmployeeService.java

package com.sample.app.service;

import java.util.List;

import com.sample.app.model.Employee;

public interface EmployeeService {

	public List<Employee> emps();

	public Employee byId(int id);

	public List<Employee> containsName(String name);

	public Employee addEmployee(Employee emp);

	public Employee updateEmployee(int id, Employee emp);

	public Employee deleteEmployee(int id);

}

EmployeeRestClient.java

package com.sample.app.service.impl;

import java.util.List;

import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.util.UriComponentsBuilder;

import com.sample.app.model.Employee;
import com.sample.app.service.EmployeeService;

public class EmployeeRestClient implements EmployeeService {

	private WebClient webClient;

	public EmployeeRestClient(WebClient webClient) {
		this.webClient = webClient;
	}

	@Override
	public List<Employee> emps() {

		return webClient.get().uri("api/v1/employees").retrieve().bodyToFlux(Employee.class).collectList().block();
	}

	@Override
	public Employee byId(int id) {
		return webClient.get().uri("api/v1/employees/" + id).retrieve().bodyToMono(Employee.class).block();
	}

	@Override
	public List<Employee> containsName(String name) {
		String uriToHit = UriComponentsBuilder.fromUriString("api/v1/employees/by-name/").queryParam("empName", name)
				.buildAndExpand().toString();

		return webClient.get().uri(uriToHit).retrieve().bodyToFlux(Employee.class).collectList().block();
	}

	@Override
	public Employee addEmployee(Employee emp) {
		return webClient.post().uri("api/v1/employees").syncBody(emp).retrieve().bodyToMono(Employee.class).block();
	}

	@Override
	public Employee updateEmployee(int id, Employee emp) {
		return webClient.put().uri("api/v1/employees/" + id).syncBody(emp).retrieve().bodyToMono(Employee.class)
				.block();
	}

	@Override
	public Employee deleteEmployee(int id) {
		return webClient.delete().uri("api/v1/employees/" + id).retrieve().bodyToMono(Employee.class).block();
	}

}

pom.xml

<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>com.sample.app</groupId>
	<artifactId>employee-rest-client</artifactId>
	<version>1</version>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.1.6.RELEASE</version>
	</parent>


	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-webflux</artifactId>
		</dependency>

		<dependency>
			<groupId>com.github.tomakehurst</groupId>
			<artifactId>wiremock-jre8-standalone</artifactId>
			<version>2.26.3</version>
			<scope>test</scope>
		</dependency>

		<!-- https://mvnrepository.com/artifact/junit/junit -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<scope>test</scope>
		</dependency>


	</dependencies>
</project>

EmployeeRestClientTest.java

package com.sample.app.service;

import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
import static com.github.tomakehurst.wiremock.client.WireMock.anyUrl;
import static com.github.tomakehurst.wiremock.client.WireMock.get;
import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo;
import static com.github.tomakehurst.wiremock.client.WireMock.urlPathMatching;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.springframework.web.reactive.function.client.WebClient;

import com.github.tomakehurst.wiremock.common.ConsoleNotifier;
import com.github.tomakehurst.wiremock.common.Json;
import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
import com.github.tomakehurst.wiremock.extension.responsetemplating.ResponseTemplateTransformer;
import com.github.tomakehurst.wiremock.junit.WireMockRule;
import com.sample.app.model.Employee;
import com.sample.app.service.impl.EmployeeRestClient;

public class EmployeeRestClientTest {
	private static final int HTTP_SERVICE_PORT = 8888;
	private static final int HTTPS_SERVICE_PORT = 9999;

	private List<Employee> ALL_EMPLOYEES = new ArrayList<>();

	private EmployeeRestClient empRestClient;
	private String baseURI;

	private static int idCounter = 1;

	private static Employee buildEmployee(String firstName, String lastName) {
		Employee emp = new Employee();
		emp.setId(idCounter);
		emp.setFirstName(firstName);
		emp.setLastName(lastName);

		idCounter++;

		return emp;
	}

	@Before
	public void initializeEmployees() {
		Employee emp1 = buildEmployee("Deepak", "Moud");
		Employee emp2 = buildEmployee("Srinivasa Rao", "Gumma");
		Employee emp3 = buildEmployee("Purna Chandra", "Rao");
		Employee emp4 = buildEmployee("Madhavi Latha", "Gumma");
		Employee emp5 = buildEmployee("Raghava", "Reddy");
		Employee emp6 = buildEmployee("Ramesh Chandra", "Dokku");

		ALL_EMPLOYEES.addAll(Arrays.asList(emp1, emp2, emp3, emp4, emp5, emp6));
	}

	@Before
	public void setup() {
		baseURI = "http://localhost:" + wireMockRule.port() + "/";
		// System.out.println("baseURI : " + baseURI);

		WebClient webClient = WebClient.create(baseURI);
		empRestClient = new EmployeeRestClient(webClient);
	}

	@Rule
	public WireMockRule wireMockRule = new WireMockRule(
			WireMockConfiguration.options().port(HTTP_SERVICE_PORT).httpsPort(HTTPS_SERVICE_PORT)
					.notifier(new ConsoleNotifier(true)).extensions(new ResponseTemplateTransformer(true)));

	@Test
	public void allEmployeeForAnyURL() {

		wireMockRule.stubFor(get(anyUrl()).willReturn(aResponse().withStatus(200)
				.withHeader("Content-Type", "application/json").withBody(Json.write(ALL_EMPLOYEES))));

		List<Employee> resultFromService = empRestClient.emps();

		assertEquals(resultFromService.size(), 6);

	}

	@Test
	public void allEmployeeForEactURLPath() {

		wireMockRule.stubFor(get(urlPathEqualTo("/api/v1/employees")).willReturn(aResponse().withStatus(200)
				.withHeader("Content-Type", "application/json").withBody(Json.write(ALL_EMPLOYEES))));

		List<Employee> resultFromService = empRestClient.emps();

		assertEquals(resultFromService.size(), 6);

	}

	@Test
	public void getEmployeeById() {

		Employee emp = new Employee();
		emp.setId(Integer.MAX_VALUE);
		emp.setFirstName("Chamu");
		emp.setLastName("Gurram");

		wireMockRule.stubFor(get(urlPathMatching("/api/v1/employees/[1-5]")).willReturn(
				aResponse().withStatus(200).withHeader("Content-Type", "application/json").withBody(Json.write(emp))));

		for (int i = 1; i < 6; i++) {

			Employee resultEmp = empRestClient.byId(1);

			assertNotNull(resultEmp);
			assertEquals(Integer.MAX_VALUE, resultEmp.getId());
			assertEquals("Chamu", resultEmp.getFirstName());
			assertEquals("Gurram", resultEmp.getLastName());

		}

	}

	@Test
	public void allEmployeeFromFile() {

		wireMockRule.stubFor(get(urlPathEqualTo("/api/v1/employees")).willReturn(aResponse().withStatus(200)
				.withHeader("Content-Type", "application/json").withBodyFile("allEmployees.json")));

		List<Employee> resultFromService = empRestClient.emps();

		assertEquals(resultFromService.size(), 2);

		Employee emp = resultFromService.get(0);

		if (emp.getId() == 1) {
			assertEquals("Ram", emp.getFirstName());
			assertEquals("Ponnam", emp.getLastName());
		} else if (emp.getId() == 2) {
			assertEquals("Lakshman", emp.getFirstName());
			assertEquals("Gurram", emp.getLastName());
		}

	}

	@Test
	public void getEmployeeByIdUsingResponseTemplate() {

		wireMockRule.stubFor(get(urlPathMatching("/api/v1/employees/3")).willReturn(aResponse().withStatus(200)
				.withHeader("Content-Type", "application/json").withBodyFile("employeeByIdTemplate.json")));

		Employee resultEmp = empRestClient.byId(3);

		assertNotNull(resultEmp);
		assertEquals(3, resultEmp.getId());
		assertEquals("Ram", resultEmp.getFirstName());
		assertEquals("Ponnam", resultEmp.getLastName());

	}

}

allEmployees.json

[
	{
		"id": 1,
		"firstName": "Ram",
		"lastName": "Ponnam"
	},
	{
		"id": 2,
		"firstName": "Lakshman",
		"lastName": "Gurram"
	}
]

employeeByIdTemplate.json

{
	"id": "{{request.path.[3]}}",
	"firstName": "Ram",
	"lastName": "Ponnam"
}

Total project structure looks like below.


Run EmployeeRestClientTest.java to run test cases.

 

You can download the complete working application from this link.

 

Reference

http://wiremock.org/docs/response-templating/




Previous                                                    Next                                                    Home

No comments:

Post a Comment