1. Overview
In this article, we’ll have a look at the Hoverfly Java library – which provides an easy way of creating real API stubs/simulations.
2. Maven Dependencies
To use Hoverfly, we need to add a single Maven dependency:
<dependency>
<groupId>io.specto</groupId>
<artifactId>hoverfly-java</artifactId>
<version>0.8.1</version>
</dependency>
The newest version can be found here.
3. Simulating an API
First, we’ll configure Hoverfly to run in the simulation mode. The simplest way to define a simulation is by using a DSL.
Let’s start with a simple example by instantiating the HoverflyRule instance:
public static final HoverflyRule rule
= HoverflyRule.inSimulationMode(dsl(
service("http://www.baeldung.com")
.get("/api/courses/1")
.willReturn(success().body(
jsonWithSingleQuotes("{'id':'1','name':'HCI'}"))));
The SimulationSource class provides a dsl method for initiating the API definition. Also, HoverflyDSL‘s service method allows us to define an endpoint and associated request paths.
Then we call willReturn to state which response we want to get in return. We also used success method of ResponseBuilder to set response status and body.
4. Using JUnit for Testing
Stubbed API can be easily tested using JUnit.
Let’s create a simple test sending an HTTP request and see if it reaches the endpoint:
responseEntity<String> courseResponse
= restTemplate.getForEntity("http://www.baeldung.com/api/courses/1", String.class);
assertEquals(HttpStatus.OK, courseResponse.getStatusCode());
assertEquals("{\"id\":\"1\",\"name\":\"HCI\"}", courseResponse.getBody());
We used Spring Web module’s RestTemplate class instance to send an HTTP request.
5. Adding Delays
Delays can be added globally, for particular HTTP method, or for a specific API call.
Here is the example code setting delay on requests with POST method:
SimulationSource.dsl(
service("http://www.baeldung.com")
.post("/api/courses")
.willReturn(success())
.andDelay(3, TimeUnit.SECONDS)
.forMethod("POST")
)
6. Request Matcher
HoverflyMatchers factory class provides several matchers including exactMatch and globMatch for URLs. For HTTP body it provides.
For HTTP bodies it provides JSON/XML exact match and JSONPath/XPath matches.
By default, the exactMatch matcher is used for both URL and body matching.
Here is example use of different matchers:
SimulationSource.dsl(
service(matches("www.*dung.com"))
.get(startsWith("/api/student"))
.queryParam("page", any())
.willReturn(success())
.post(equalsTo("/api/student"))
.body(equalsToJson(jsonWithSingleQuotes("{'id':'1','name':'Joe'}")))
.willReturn(success())
.put("/api/student/1")
.body(matchesJsonPath("$.name"))
.willReturn(success())
.post("/api/student")
.body(equalsToXml("<student><id>2</id><name>John</name></student>"))
.willReturn(success())
.put("/api/student/2")
.body(matchesXPath("/student/name"))
.willReturn(success()));
)
In this example, matches method checks URL with globMatch that allows wildcard search.
Then startsWith checks if the request path starts with “*/api/student*“. We used any matcher to allow all possible values in page query parameter.
The equalsToJson matcher makes sure that the body payload matches the exact JSON given here. The matchesJsonPath method for checking with an element at particular JSON Path exists or not.
Similarly, equalsToXml matches the XML given in request body with the one given here. The matchesXPath matches a body with an XPath expression.
7. Conclusion
In this quick tutorial, we discussed the usage of Hoverfly Java library. We looked into simulating HTTP services, DSL for configuring endpoints, adding delays and use of request matchers. We also looked into testing these services using JUnit.
As always, code snippets, as always, can be found over on GitHub.