DSL for setting up WireMock mappings.
npm install wiremock-mapper



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)
``bash`
npm install wiremock-mapper
`typescript
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.
`typescript
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
`
`typescript
import { Configuration } from 'wiremock-mapper';
// Clear all global mappings
Configuration.reset();
`
Import the library
`typescript`
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.
`typescript`
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.
`typescript`
await WireMockMapper.createMapping((req, res) => {
req.isAGet.withUrlPath.matching('/my/.*/path');
});
#### Interfaces
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()
`typescript`
await WireMockMapper.createMapping((req, res) => {
res
.withJsonBody({
someKey: 'theValue',
otherKey: 'otherValue'
})
.withStatus(200)
.withStatusMessage('ok');
});
#### Interface
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 |
`typescript`
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
`typescript`
await WireMockMapper.getRequests();
Get all requests for a given stub id
`typescript`
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.
`typescript
import { wiremockMapperMatchers } from 'wiremock-mapper';
// Extend Jest with WireMock matchers
expect.extend(wiremockMapperMatchers);
`
#### toHaveBeenRequested(options?)
Verifies that a stub received at least one request.
`typescript
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 });
`
#### toHaveBeenRequestedWith(expected, options?)
Verifies that a stub received a request with the specified payload.
`typescript
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: 'john@example.com' };
// 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);
`
#### toHaveBeenRequestedTimes(expectedCount, options?)
Verifies that a stub received exactly the specified number of requests.
`typescript
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:
`typescript
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:
`typescript`
// 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 |
`typescript
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: 'john@example.com' };
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