wiremock-mapper
v0.7.2
Published
DSL for setting up WireMock mappings.
Readme
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.
Prerequisites
- A running WireMock server (default:
http://localhost:8080) - Node.js 12+
- TypeScript (recommended)
Installation
npm install wiremock-mapperConfiguring
import { Configuration } from 'wiremock-mapper';
Configuration.wireMockBaseUrl = 'http://localhost:8080/some_path_prefix'; // default is 'http://localhost:8080'Creating a global mapping
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 configurationsReset global mapping
import { Configuration } from 'wiremock-mapper';
// Clear all global mappings
Configuration.reset();Create a mapping
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) => {});Define matching parameters
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');
});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 |
Define response behavior
Responses are created from res provided by WireMockMapper.createMapping()
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 |
Example
await WireMockMapper.createMapping((req, res) => {
req.isAGet.withUrlPath.equalTo('/my/api/path');
res
.withJsonBody({
someKey: 'theValue',
otherKey: 'otherValue'
})
.withStatus(200)
.withStatusMessage('ok');
});Get Requests Received
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.
Jest Matchers
The library provides custom Jest matchers for testing WireMock interactions with built-in retry logic for handling asynchronous operations.
Setup
import { wiremockMapperMatchers } from 'wiremock-mapper';
// Extend Jest with WireMock matchers
expect.extend(wiremockMapperMatchers);Available Matchers
toHaveBeenRequested(options?)
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 });toHaveBeenRequestedWith(expected, options?)
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);toHaveBeenRequestedTimes(expectedCount, options?)
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);Global Matcher Configuration
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 });Matcher Options
| Option | Type | Default | Description |
| --------- | -------- | ------- | -------------------------------------------------- |
| retries | number | 15 | Number of retry attempts when waiting for requests |
| delay | number | 200 | Delay in milliseconds between retry attempts |
Example Test
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);
});
});Troubleshooting
Common Issues
WireMock server not running
- Ensure WireMock is running on the expected port (default: 8080)
- Check if the
Configuration.wireMockBaseUrlis 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.jsonincludes the necessary type definitions
Getting Help
- 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
