DSL for setting up WireMock mappings
A TypeScript/JavaScript library that provides a fluent API for creating WireMock mappings. WireMock is a simulator for HTTP-based APIs that allows you to stub and mock web services during development and testing.
- A running WireMock server (default:
http://localhost:8080
) - Node.js 12+
- TypeScript (recommended)
npm install wiremock-mapper
import { Configuration } from 'wiremock-mapper';
Configuration.wireMockBaseUrl = 'http://localhost:8080/some_path_prefix'; // default is 'http://localhost:8080'
Global mappings are a way to predefine part of your request/response configuration that will be applied to all mappings created afterwards.
import { Configuration } from 'wiremock-mapper';
// Set up global configuration that applies to all future mappings
Configuration.createGlobalMapping((request, response) => {
// Add common headers to all requests
request.withHeader('Authorization').equalTo('Bearer token123');
// Add common response headers
response.withHeader('Content-Type').equalTo('application/json');
response.withHeader('X-API-Version').equalTo('v1');
});
// Now all subsequent mappings will include these configurations
import { Configuration } from 'wiremock-mapper';
// Clear all global mappings
Configuration.reset();
Import the library
import { WireMockMapper } from 'wiremock-mapper';
Mappings are created with WireMockMapper.createMapping()
which takes a function argument defining the mock behavior. It asynchronously sends the configuration to the WireMock server.
await WireMockMapper.createMapping((req, res) => {});
All request modifiers are set from req
provided by createMapping
, and return an instance of RequestBuilder
, MatchBuilder
, or UrlMatchBuilder
. These can be chained together to form a complete request expectation.
It should read like a sentence when set up properly.
await WireMockMapper.createMapping((req, res) => {
req.isAGet.withUrlPath.matching('/my/.*/path');
});
RequestBuilder
Method | Argument(s) | Effect | Returns |
---|---|---|---|
isAGet |
none | sets request method to GET |
RequestBuilder |
isAPost |
none | sets request method to POST |
RequestBuilder |
isAPut |
none | sets request method to PUT |
RequestBuilder |
isADelete |
none | sets request method to DELETE |
RequestBuilder |
isAHead |
none | sets request method to HEAD |
RequestBuilder |
isAnOptions |
none | sets request method to OPTIONS |
RequestBuilder |
isATrace |
none | sets request method to TRACE |
RequestBuilder |
isAnyVerb |
none | sets request method to ANY |
RequestBuilder |
withBody |
none | sets request body | RequestBuilder |
withBasicAuth |
username: string, password: string |
sets basic auth | RequestBuilder |
withUrl |
none | sets expected URL | UrlMatchBuilder |
withUrlPath |
none | sets URL path match to urlPathPattern |
UrlMatchBuilder |
withCookie |
key: string |
sets request cookie | MatchBuilder |
withHeader |
key: string |
sets request header | MatchBuilder |
withQueryParam |
key: string |
sets request query parameter | MatchBuilder |
UrlMatchBuilder
Method | Arguments | Effect | Returns |
---|---|---|---|
equalTo |
url: string |
Matches text given | RequestBuilder |
matching |
regexp: string |
Matches with regular expression | RequestBuilder |
MatchBuilder
Method | Argument(s) | Returns |
---|---|---|
absent |
none | RequestBuilder |
containing |
value: string |
RequestBuilder |
equalTo |
value: string |
RequestBuilder |
equalToJson |
json: any, ignoreArrayOrder: boolean, ignoreExtraElements: boolean |
RequestBuilder |
equalToXml |
xml: string |
RequestBuilder |
matching |
value: string |
RequestBuilder |
matchingJsonPath |
path: string |
RequestBuilder |
matchingXPath |
xpath: string |
RequestBuilder |
notMatching |
value: string |
RequestBuilder |
Responses are created from res
provided by WireMockMapper.createMapping()
await WireMockMapper.createMapping((req, res) => {
res
.withJsonBody({
someKey: 'theValue',
otherKey: 'otherValue'
})
.withStatus(200)
.withStatusMessage('ok');
});
ResponseBuilder
Method | Argument(s) | Returns |
---|---|---|
withBody |
value: string |
ResponseBuilder |
withDelay |
milliseconds: number |
ResponseBuilder |
withHeader |
key: string |
ResponseBuilder |
withJsonBody |
value: object |
ResponseBuilder |
withStatus |
statusCode: object |
ResponseBuilder |
withStatusMessage |
statusMessage: string |
ResponseBuilder |
withTransformer |
transformerName: string |
ResponseBuilder |
await WireMockMapper.createMapping((req, res) => {
req.isAGet.withUrlPath.equalTo('/my/api/path');
res
.withJsonBody({
someKey: 'theValue',
otherKey: 'otherValue'
})
.withStatus(200)
.withStatusMessage('ok');
});
Get all requests
await WireMockMapper.getRequests();
Get all requests for a given stub id
await WireMockMapper.getRequests({ stubId: 'some_stub_id' });
The interface for the returned object can be found here.
The library provides custom Jest matchers for testing WireMock interactions with built-in retry logic for handling asynchronous operations.
import { wiremockMapperMatchers } from 'wiremock-mapper';
// Extend Jest with WireMock matchers
expect.extend(wiremockMapperMatchers);
Verifies that a stub received at least one request.
const stubId = await WireMockMapper.createMapping((req, res) => {
req.isAGet.withUrlPath.equalTo('/api/users');
res.withJsonBody([]).withStatus(200);
});
// Make API call
await fetch('http://localhost:8080/api/users');
// Verify the stub was called
await expect(stubId).toHaveBeenRequested();
// With custom retry options
await expect(stubId).toHaveBeenRequested({ retries: 5, delay: 100 });
Verifies that a stub received a request with the specified payload.
const stubId = await WireMockMapper.createMapping((req, res) => {
req.isAPost.withUrlPath.equalTo('/api/users');
res.withJsonBody({ id: 123 }).withStatus(201);
});
const userData = { name: 'John Doe', email: '[email protected]' };
// Make API call with payload
await fetch('http://localhost:8080/api/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(userData)
});
// Verify the stub was called with expected payload
await expect(stubId).toHaveBeenRequestedWith(userData);
Verifies that a stub received exactly the specified number of requests.
const stubId = await WireMockMapper.createMapping((req, res) => {
req.isAGet.withUrlPath.equalTo('/api/health');
res.withBody('OK').withStatus(200);
});
// Make multiple API calls
await fetch('http://localhost:8080/api/health');
await fetch('http://localhost:8080/api/health');
await fetch('http://localhost:8080/api/health');
// Verify the stub was called exactly 3 times
await expect(stubId).toHaveBeenRequestedTimes(3);
You can configure global defaults for all matchers:
import { Configuration } from 'wiremock-mapper';
// Set global retry options
Configuration.setMatcherOptions({
retries: 10, // Number of retry attempts (default: 15)
delay: 100 // Delay between retries in milliseconds (default: 200)
});
Individual matchers can override global settings:
// Override global settings for this specific assertion
await expect(stubId).toHaveBeenRequested({ retries: 3, delay: 50 });
Option | Type | Default | Description |
---|---|---|---|
retries |
number |
15 |
Number of retry attempts when waiting for requests |
delay |
number |
200 |
Delay in milliseconds between retry attempts |
import {
WireMockMapper,
Configuration,
wiremockMapperMatchers
} from 'wiremock-mapper';
expect.extend(wiremockMapperMatchers);
describe('API Tests', () => {
beforeAll(() => {
Configuration.wireMockBaseUrl = 'http://localhost:8080';
});
beforeEach(async () => {
await WireMockMapper.clearAllMappings();
});
it('should handle user creation', async () => {
const stubId = await WireMockMapper.createMapping((req, res) => {
req.isAPost.withUrlPath.equalTo('/api/users');
res.withJsonBody({ id: 123, name: 'John Doe' }).withStatus(201);
});
const userData = { name: 'John Doe', email: '[email protected]' };
await fetch('http://localhost:8080/api/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(userData)
});
await expect(stubId).toHaveBeenRequestedWith(userData);
});
});
WireMock server not running
- Ensure WireMock is running on the expected port (default: 8080)
- Check if the
Configuration.wireMockBaseUrl
is correctly set
Connection refused errors
- Verify the WireMock server URL and port
- Check if there are any firewall restrictions
- Ensure the WireMock server is accessible from your application
Mapping not working as expected
- Check the WireMock server logs for any errors
- Verify your request matching patterns are correct
- Use
WireMockMapper.getRequests()
to see what requests were actually received
TypeScript compilation errors
- Ensure you have the latest version of TypeScript installed
- Check that your
tsconfig.json
includes the necessary type definitions
- Check the GitHub Issues for existing problems
- Review the WireMock documentation for underlying concepts
- Create a new issue with a minimal reproduction case if needed