Mocking OpenAPI services using WireMock
This document describes how to mock OpenAPI services using WireMock. The testing procedure described in this document is based on the serverless-workflow-service-calls-quarkus
example application.
WireMock is an open source Mocking API for unit, integration, and performance tests. You can use WireMock to isolate your tests from third party APIs and prototype APIs that do not exist.
The examples used in this document assumes that you have the following prerequisites:
-
Required tooling is installed. For more information, see Getting familiar with SonataFlow tooling.
-
A workflow project is created and orchestrates OpenAPI services.
For more information about orchestrating OpenAPI services, see Orchestrating the OpenAPI services.
Adding a mocked OpenAPI service to your tests
The procedure in this section describes how you can add WireMock to your workflow application.
-
A workflow project is created.
For more information about creating a workflow project, see Creating your first Serverless Workflow service.
-
Add the following WireMock dependency to the
pom.xml
file of your project:Add WireMock dependency topom.xml
<dependency> <groupId>com.github.tomakehurst</groupId> <artifactId>wiremock-jre8</artifactId> <version>{wiremock.version}</version> <scope>test</scope> </dependency>
Replace
{wiremock.version}
variable with the version of WireMock that you want to use. -
Select one of the following methods to start your WireMock server:
-
You can start the WireMock server as a
QuarkusTestResource
. If you select this method, then the WireMock server is started once before you run any test, and the server is stopped when the test finishes. This option is suitable for most use cases. -
You can start the WireMock server independently for each test. This option is useful when you want each test to behave differently.
For more information about starting the WireMock server, see Starting WireMock server as a
QuarkusTestResource
and Starting WireMock server for a specific test. -
-
Start the WireMock server as shown in the following example:
Example of starting a WireMock serverWireMockConfiguration config = WireMockConfiguration.wireMockConfig().dynamicPort(); (1) WireMockServer wireMockServer = new WireMockServer(config); (2) wireMockServer.start(); (3)
1 Creates the configuration for the WireMock server. You can use a dynamic port since it prevents the tests from failing due to port conflicts. When you cannot use a dynamic port, you can use the WireMockConfiguration#port(int)
method to use a fixed port number.2 Creates the WireMock server instance. 3 Starts the WireMock server. -
Mock the endpoints as shown in the following example:
Example of mocking endpointsObjectMapper objectMapper = new ObjectMapper(); JsonNode greecePayload = objectMapper.readTree(getClass().getResourceAsStream("/country_mock.json")); (1) wireMockServer.stubFor(WireMock.get(WireMock.urlEqualTo("/rest/v2/name/Greece")) (2) .willReturn(WireMock.aResponse() (3) .withStatus(200) (4) .withHeader("Content-Type", "application/json") (5) .withJsonBody(greecePayload))); (6)
1 Creates the JSON payload, which the WireMock server returns. Alternatively, you can use the ResponseDefinitionBuilder#withBody
method to define aString
or abyte[]
as the response body.2 Defines a stub for the /rest/v2/name/Greece
endpoint.3 Defines the response for the stub. 4 Defines the response status. 5 Defines the response headers. 6 Defines the response body. -
Stop the WireMock server as shown in the following example:
Example of stopping a WireMock serverwireMockServer.stop();
Starting WireMock server as a QuarkusTestResource
In the process of adding a mocked OpenAPI service to your tests, you need to start the WireMock server. You can start the WireMock server either as a QuarkusTestResource
or you can start the server for each test.
The procedure in this section describes how you can start the WireMock server as a QuarkusTestResource
. For more information about QuarkusTestResource
, see Starting services before the Quarkus application starts document.
-
A workflow project is created.
For more information about creating a workflow project, see Creating your first Serverless Workflow service.
-
WireMock dependency is added in the
pom.xml
file.
-
Create a class that implements the
QuarkusTestResource
interface as shown in the following example:Example implementation ofQuarkusTestResource
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.github.tomakehurst.wiremock.WireMockServer; import com.github.tomakehurst.wiremock.core.WireMockConfiguration; import io.quarkus.test.common.QuarkusTestResourceLifecycleManager; import java.io.IOException; import java.io.UncheckedIOException; import java.util.Map; import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; import static com.github.tomakehurst.wiremock.client.WireMock.get; import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; public class RestCountriesMockServer implements QuarkusTestResourceLifecycleManager { private WireMockServer wireMockServer; @Override public Map<String, String> start() { (1) configureWiremockServer(); return Map.of("quarkus.rest-client.restcountries_json.url", wireMockServer.baseUrl() + "/rest"); (2) } private void configureWiremockServer() { wireMockServer = new WireMockServer(WireMockConfiguration.wireMockConfig().dynamicPort()); wireMockServer.start(); ObjectMapper objectMapper = new ObjectMapper(); JsonNode greecePayload; try { greecePayload = objectMapper.readTree(getClass().getResourceAsStream("/country_mock.json")); } catch (IOException e) { throw new UncheckedIOException(e); } wireMockServer.stubFor(get(urlEqualTo("/rest/v2/name/Greece")) .willReturn(aResponse() .withStatus(200) .withHeader("Content-Type", "application/json") .withJsonBody(greecePayload))); } @Override public void stop() { (3) if (wireMockServer != null) { wireMockServer.stop(); } } }
1 Starts the test resource. This method is called once before running all the tests. 2 Returns a map of application properties that are set in the test environment. In this case, the quarkus.rest-client.restcountries_json.url
property is set as the base URL of the WireMock server.3 Stops the test resource. This method is called once after running all the tests. -
Use the
QuarkusTestResource
implementation in your test class as shown in the following example:Example of a test class using theQuarkusTestResource
implementationimport io.quarkus.test.common.QuarkusTestResource; import io.quarkus.test.junit.QuarkusTest; import org.junit.jupiter.api.Test; @QuarkusTest @QuarkusTestResource(RestCountriesMockServer.class) (1) class CountryServiceWorkflowTest { @Test void testFeatureA() { // ... } @Test void testFeatureB() { // ... } }
1 Uses the RestCountriesMockServer
class as a test resource.
Starting WireMock server for a specific test
You can also start the WireMock server to be used in a specific test.
-
A workflow project is created.
For more information about creating a workflow project, see Creating your first Serverless Workflow service.
-
WireMock dependency is added in the
pom.xml
file.
-
Wrap the logic of a test between starting and stopping the WireMock server as shown in the following example:
Example of a test using a specific WireMock server instanceimport com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.github.tomakehurst.wiremock.WireMockServer; import com.github.tomakehurst.wiremock.core.WireMockConfiguration; import io.quarkus.test.junit.QuarkusTest; import org.junit.jupiter.api.Test; import java.io.IOException; import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; import static com.github.tomakehurst.wiremock.client.WireMock.get; import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; @QuarkusTest class CountryServiceWorkflowTest { @Test void testFeatureA() throws IOException { WireMockServer wireMockServer = startWiremockServerForFeatureA(); try { // test logic } finally { wireMockServer.stop(); } } @Test void testFeatureB() { WireMockServer wireMockServer = startWiremockServerForFeatureB(); try { // test logic } finally { wireMockServer.stop(); } } private static WireMockServer startWiremockServerForFeatureA() throws IOException { WireMockServer wireMockServer = new WireMockServer(WireMockConfiguration.wireMockConfig().dynamicPort()); wireMockServer.start(); ObjectMapper objectMapper = new ObjectMapper(); JsonNode greecePayload = objectMapper.readTree(CountryServiceWorkflowTest.class.getResourceAsStream("/country_mock_feature_a.json")); wireMockServer.stubFor(get(urlEqualTo("/rest/v2/name/Greece")) .willReturn(aResponse() .withStatus(200) .withHeader("Content-Type", "application/json") .withJsonBody(greecePayload))); return wireMockServer; } private static WireMockServer startWiremockServerForFeatureB() { WireMockServer wireMockServer = new WireMockServer(WireMockConfiguration.wireMockConfig().dynamicPort()); wireMockServer.start(); wireMockServer.stubFor(get(urlEqualTo("/rest/v2/name/Greece")) .willReturn(aResponse().withStatus(404))); return wireMockServer; } }
You can test your workflow application using the instructions described in Testing your workflow application using REST Assured document.
Found an issue?
If you find an issue or any misleading information, please feel free to report it here. We really appreciate it!