UNPKG

mockserver-client

Version:

A node client for the MockServer

432 lines (357 loc) 16.3 kB
# mockserver-client-node > Communicate with a [MockServer](https://mock-server.com/) from any node or grunt build [![Build status](https://badge.buildkite.com/368c3b69e959f29725d8ab582f8d75dedddceee196d39b6d28.svg?style=square&theme=slack)](https://buildkite.com/mockserver/mockserver-client-node) [![NPM](https://nodei.co/npm/mockserver-client.png?downloads=true&stars=true)](https://nodei.co/npm/mockserver-client/) # Community * Roadmap:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="https://github.com/orgs/mock-server/projects/1"><img height="20px" src="https://mock-server.com/images/GitHub_Logo-md.png" alt="GitHub Project"></a> * Feature Requests:&nbsp;&nbsp;&nbsp;<a href="https://github.com/mock-server/mockserver-monorepo/issues"><img height="20px" src="https://mock-server.com/images/GitHub_Logo-md.png" alt="Github Issues"></a> * Issues / Bugs:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="https://github.com/mock-server/mockserver-monorepo/issues"><img height="20px" src="https://mock-server.com/images/GitHub_Logo-md.png" alt="Github Issues"></a> * Discussions:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="https://github.com/mock-server/mockserver-monorepo/discussions"><img height="20px" src="https://mock-server.com/images/GitHub_Logo-md.png" alt="GitHub Discussions"></a> ## Getting Started [MockServer](https://mock-server.com/) allows you to mock any system you integrate with via HTTP or HTTPS (i.e. (REST) services, web sites, etc). Please note that it is a third party project that needs java. This npm module allows any grunt or node project to easily communicate with a running [MockServer](https://mock-server.com/) instance. As an addition to this module for communicating with a running MockServer there is a second project that can be used to start and stop a MockServer called [mockserver-node](https://www.npmjs.org/package/mockserver-node). The MockServer client can be created as follows: ```js var mockServer = require('mockserver-client'), mockServerClient = mockServer.mockServerClient // MockServer and proxy client ``` **Note:** this assumes you have an instance of MockServer running on port 1080. For more information on how to do so check [mockserver-node](https://www.npmjs.org/package/mockserver-node). ## Setup Expectation A simple expectation can be set up as follows: ```js mockServerClient("localhost", 1080) .mockSimpleResponse('/somePath', { name: 'value' }, 203) .then( function(result) { // do something next }, function(error) { // handle error } ); ``` A more complex expectation can be set up like this: ```js mockServerClient("localhost", 1080) .mockAnyResponse( { 'httpRequest': { 'method': 'POST', 'path': '/somePath', 'queryStringParameters': [ { 'name': 'test', 'values': [ 'true' ] } ], 'body': { 'type': "STRING", 'value': 'someBody' } }, 'httpResponse': { 'statusCode': 200, 'body': JSON.stringify({ name: 'value' }), 'delay': { 'timeUnit': 'MILLISECONDS', 'value': 250 } }, 'times': { 'remainingTimes': 1, 'unlimited': false } } ) .then( function(result) { // do something next }, function(error) { // handle error } ); ``` For the full documentation see [MockServer - Creating Expectations](https://mock-server.com/mock_server/creating_expectations.html). ### Fluent `when().respond()` API The same expectation can also be built with a chainable API that mirrors the Java client's `when(...)` / `ForwardChainExpectation`: ```js mockServerClient("localhost", 1080) .when({ path: '/somePath' }) .respond({ statusCode: 200, body: 'some_response_body' }); ``` To set the number of matches, time-to-live, priority or expectation id, use the chainable `.withTimes()` / `.withTimeToLive()` / `.withPriority()` / `.withId()` builders before the terminal action — this is the **recommended** style because it is unambiguous and order-independent: ```js mockServerClient("localhost", 1080) .when({ path: '/somePath' }) .withTimes(2) .withTimeToLive({ unlimited: false, timeToLive: 60, timeUnit: 'SECONDS' }) .withPriority(10) .withId('my-id') .forward({ host: 'localhost', port: 8081 }); ``` > **⚠️ Positional argument order differs from the procedural methods.** `when(...)` > takes its optional arguments as `when(request, times, timeToLive, priority)` to > match the **Java** client. This is **not** the order used by the Node procedural > methods (`mockSimpleResponse`, `respondWith*`, etc.), which take > `(…, times, priority, timeToLive, id)`. In particular `when(req, 2, 5)` sets > `timeToLive = 5` (which expects an object, so it is ignored) and leaves the > priority unset — it does **not** set the priority to `5`. To avoid this footgun, > prefer the `.withTimes()` / `.withTimeToLive()` / `.withPriority()` builders shown > above rather than positional arguments. If you do pass them positionally, the order is `(request, times, timeToLive, priority)`: ```js mockServerClient("localhost", 1080) .when({ path: '/somePath' }, 2, { unlimited: false, timeToLive: 60, timeUnit: 'SECONDS' }, 10) .respond({ statusCode: 201 }); ``` The chain returned by `when(...)` exposes the builders `withTimes`, `withTimeToLive`, `withPriority`, `withId` and the terminal actions `respond` (httpResponse, a template, or a class-callback), `forward` (httpForward, a template, a class-callback, or an override-forwarded-request), `error` (httpError), `callback` (a local JS response callback over the callback WebSocket) and `forwardCallback` (a local JS forward callback). The action is auto-detected from the object shape: a plain object with a string `template`/`templateType` becomes a template action, one with a `callbackClass` becomes a server-side class-callback, otherwise it is the natural response/forward action. Each terminal method returns the same promise as the procedural builders, so it can be awaited or used with `.then(...)`. ### Advanced Response Builders For non-HTTP and streaming protocols there are dedicated builders that take a path (or full request matcher) plus the response action object, with optional `times`, `priority`, `timeToLive`, and `id` arguments: ```javascript // Server-Sent Events (SSE) client.respondWithSse('/events', { events: [ { event: 'message', data: 'first' }, { event: 'message', data: 'second' } ], closeConnection: true }); // WebSocket client.respondWithWebSocket('/ws', { messages: [ { text: 'hello' } ], closeConnection: false }); // DNS client.respondWithDns('example.com', { answerRecords: [ { name: 'example.com', type: 'A', ttl: 300, value: '127.0.0.1' } ], responseCode: 'NOERROR' }); // Raw binary client.respondWithBinary('/binary', { binaryData: Buffer.from('hello').toString('base64') }); // gRPC server-streaming client.respondWithGrpcStream('/my.Service/StreamItems', { statusName: 'OK', messages: [ { json: '{"value":"first"}' }, { json: '{"value":"second"}' } ], closeConnection: true }); ``` ### AI Agent Mock Builders (MCP & A2A) Declarative builders generate the full set of expectations needed to mock an AI agent endpoint. `client.mcpMock(path)` mocks an [MCP](https://modelcontextprotocol.io) (Model Context Protocol) server, and `client.a2aMock(path)` mocks an [A2A](https://a2a-protocol.org) (Agent-to-Agent) agent. Both return a fluent builder; call `.applyTo()` to register the generated expectations, or `.build()` to obtain the raw expectation array. They are also exported as standalone factories (`require('mockserver-client').a2aMock`). ```javascript // Mock an A2A agent: a static agent-card document over GET plus JSON-RPC 2.0 // tasks/send, tasks/get and tasks/cancel over POST. client.a2aMock('/a2a') .withAgentName('TranslatorAgent') .withAgentDescription('Translates text between languages') .withSkill('translate') .withName('Translation') .withDescription('Translates text') .withTag('i18n') .withExample('Translate hello to Spanish') .and() // optional SSE streaming (advertises capabilities.streaming and streams // status-update / artifact-update events): .withStreaming() // optional push notifications (echoes the config and POSTs each completed // task to the webhook while still replying to the caller): .withPushNotifications('http://localhost:1234/callback') // custom handler matched by a regex over the inbound message text: .onTaskSend() .matchingMessage('translate.*') .respondingWith('Hola') .and() .applyTo(); // returns a promise; omit the client arg to use this client ``` ### SRE Helpers (SLO verdicts & chaos experiments) `verifySLO(criteria)` evaluates service-level objectives over the recorded SLI samples and resolves the verdict (PASS / INCONCLUSIVE); it rejects on a FAIL verdict, and on a disabled/invalid request (start MockServer with `sloTrackingEnabled=true`). `startChaosExperiment(experiment)` runs a scheduled multi-stage chaos experiment (only one experiment is active at a time). ```javascript // Evaluate SLOs over the last 60s of forwarded traffic client.verifySLO({ name: 'checkout-slo', window: { type: 'LOOKBACK', lookbackMillis: 60000 }, minimumSampleCount: 10, objectives: [ { sli: 'LATENCY_P95', comparator: 'LESS_THAN', threshold: 250 }, { sli: 'ERROR_RATE', comparator: 'LESS_THAN_OR_EQUAL', threshold: 0.01 } ] }).then( function (verdict) { /* verdict.result === 'PASS' | 'INCONCLUSIVE' */ }, function (failure) { /* FAIL verdict body, or enablement guidance */ } ); // Run a two-stage chaos experiment against an upstream host client.startChaosExperiment({ name: 'rolling-brownout', stages: [ { durationMillis: 30000, profiles: { 'api.example.com': { errorStatus: 503, errorProbability: 0.25 } } }, { durationMillis: 30000, profiles: { 'api.example.com': { latency: { value: 500, timeUnit: 'MILLISECONDS' } } } } ] }); ``` ## Verify Requests It is also possible to verify that request were made: ```js mockServerClient("localhost", 1080) .verify( { 'method': 'POST', 'path': '/somePath', 'body': 'someBody' }, 1, true ) .then( function() { // do something next }, function(failure) { // handle verification failure } ); ``` It is furthermore possible to verify that sequences of requests were made in a specific order: ```js mockServerClient("localhost", 1080) .verifySequence( { 'method': 'POST', 'path': '/somePathOne', 'body': 'someBody' }, { 'method': 'GET', 'path': '/somePathTwo' }, { 'method': 'GET', 'path': '/somePathThree' } ) .then( function() { // do something next }, function(failure) { // handle verification failure } ); ``` For the full documentation see [MockServer - Verifying Requests](https://mock-server.com/mock_server/verification.html). ## Interactive Breakpoints The client supports matcher-driven interactive breakpoints over the callback WebSocket. Register a breakpoint matcher to pause forwarded/proxied exchanges at specific phases and inspect/modify/continue them via callback handlers. ### Register a breakpoint ```js // REQUEST phase only client.addRequestBreakpoint( { path: '/api/.*' }, function (request) { // inspect or modify the request; return a request to continue or a response to abort request.path = '/api/modified'; return request; } ).then(function (breakpointId) { console.log('Breakpoint registered:', breakpointId); }); // REQUEST + RESPONSE phases client.addRequestAndResponseBreakpoint( { path: '/api/.*' }, function (request) { return request; }, // REQUEST handler function (request, response) { return response; } // RESPONSE handler ).then(function (breakpointId) { console.log('Breakpoint registered:', breakpointId); }); // All phases with stream frame handler client.addBreakpoint( { path: '/stream/.*' }, ['REQUEST', 'RESPONSE', 'RESPONSE_STREAM', 'INBOUND_STREAM'], function (request) { return request; }, function (request, response) { return response; }, function (pausedFrame) { // pausedFrame has: correlationId, streamId, sequenceNumber, direction, phase, body (base64) return { action: 'CONTINUE' }; // Other actions: MODIFY (with body), DROP, INJECT (with body), CLOSE } ).then(function (breakpointId) { console.log('Breakpoint registered:', breakpointId); }); ``` ### Manage breakpoints ```js // List all matchers client.listBreakpointMatchers().then(function (result) { console.log(result.matchers); }); // Remove a specific matcher client.removeBreakpointMatcher(breakpointId); // Clear all matchers client.clearBreakpointMatchers(); ``` ## Using in tests The client supports TC39 explicit resource management, so a `using` / `await using` binding resets the server automatically when it goes out of scope — no manual `afterEach(() => client.reset())` needed: ```js const { mockServerClient } = require('mockserver-client'); it('records the request', async () => { await using client = mockServerClient('localhost', 1080); // ... register expectations, make requests ... // the server is reset when `client` goes out of scope }); ``` If your runtime/transpiler does not yet support `await using`, reset explicitly in a Jest/Mocha hook: ```js const { mockServerClient } = require('mockserver-client'); const client = mockServerClient('localhost', 1080); afterEach(() => client.reset()); ``` ## Start / Launch MockServer This package (`mockserver-client`) is the REST/WebSocket client for communicating with a running MockServer. To **download and launch** a local MockServer instance (no Java or Docker required), use the companion [`mockserver-node`](https://www.npmjs.org/package/mockserver-node) package: ```shell npx -p mockserver-node mockserver run -p 1080 ``` `mockserver-node` downloads a self-contained platform bundle (`mockserver-<version>-<os>-<arch>`) from the GitHub Release, verifies its SHA-256, caches it per-user, and starts it. See the [mockserver-node README](https://www.npmjs.org/package/mockserver-node) for full details including environment variables (`MOCKSERVER_BINARY_BASE_URL`, `MOCKSERVER_BINARY_CACHE`, `MOCKSERVER_SKIP_BINARY_DOWNLOAD`) and supported platforms (linux/darwin/windows on x86_64/aarch64). ## Contributing In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code using [Grunt](http://gruntjs.com/). ## Changelog All notable and significant changes are detailed in the [MockServer changelog](https://github.com/mock-server/mockserver-monorepo/blob/master/changelog.md) --- Task submitted by [James D Bloom](https://blog.jamesdbloom.com) ## AI Assistant Integration MockServer includes a built-in [MCP](https://modelcontextprotocol.io) (Model Context Protocol) server that enables AI coding assistants to create expectations, verify requests, and debug HTTP traffic programmatically. - **MCP Endpoint:** `http://localhost:1080/mockserver/mcp` - **AI Documentation:** [llms.txt](https://www.mock-server.com/llms.txt) - **Setup Guide:** [AI Integration](https://www.mock-server.com/mock_server/ai_mcp_setup.html)