
Research
Malicious npm Packages Impersonate Flashbots SDKs, Targeting Ethereum Wallet Credentials
Four npm packages disguised as cryptographic tools steal developer credentials and send them to attacker-controlled Telegram infrastructure.
@teamjourney/api-mock-server
Advanced tools
API mocking library that runs as a real HTTP server in Node.js
API Mock Server can be used to test code that performs HTTP requests without calling the real service and allows full control over the request and responses.
Table of Contents
API Mock Server runs on a real port and responds to real HTTP requests. This means that it is ideal for testing or simulating HTTP requests made by any language or system without interacting with its code directly.
This approach differs to projects such as nock
which work by overriding Node's http.request
function.
Control of the mock is handled in Node.js and works well with testing frameworks such as Mocha or Jasmine.
npm install --save-dev @teamjourney/api-mock-server
or
yarn add --dev @teamjourney/api-mock-server
Tested on Node.js 10.x and 12.x
const server = require('@teamjourney/api-mock-server').default;
server.start(9001)
.then(() => {
server.mock(
{ path: '/my-endpoint' },
{ body: { data: 'something' } },
);
// Call GET http://localhost:9001/my-endpoint here
// It will return with a JSON body of { data: 'something' }
server.stop();
});
import server from '@teamjourney/api-mock-server';
const init = async () => {
await server.start(9001);
server.mock(
{ path: '/my-endpoint' },
{ body: { data: 'something' } },
);
// Call GET http://localhost:9001/my-endpoint here
// It will return with a JSON body of { data: 'something' }
server.stop();
};
init();
It's possible (but optional) to create multiple instances of the mock server running on different ports, each with their own routes and logging.
Use instances of the MockServer
class to achieve this. The below example is
in ES6 for simplicity.
import { MockServer } from '@teamjourney/api-mock-server';
const server = new MockServer();
MockServer
has the same interface as the core library functions so all of the
below functions should work.
Calling start
with a port number allows you to specify a port.
server.start(9002)
Calling start
without a port will attempt to start on a random port. It
returns a promise which resolves to http.Server
object. This allows for
finding out the port it is being run on.
server.start()
.then((httpServer) => {
const { port } = serverInfo.address();
...
});
Calling stop
will stop the server.
server.stop();
Calling reset
will keep the server running but will clear all mocks and logged
requests.
server.reset();
It's also possible to reset specific mocks by passing an array to reset
.
server.reset([ { path: '/my-endpoint' } ]);
This will remove the mock as well as removing it from the uncalled mocks list. If the mock has been called however, it will still appear in the called mocks list.
Trying to reset a mock that doesn't exist will fail silently.
Mocking requests and responses simply involves calling mock
with two
arguments. The first defines the request shape and the second the response
shape.
The simplest call would be
server.mock({ path: '/my-endpoint' });
This would handle any GET requests (the default method) to /my-endpoint
and
return am empty 200 response (the default response status).
There are numerous ways to configure specific behaviours that are defined below.
Any unmocked requests will return an empty 501 (Not Implemented) response.
Calling mock
with a request shape that matches an already mocked request will
throw an error.
server.mock({ path: '/my-endpoint' });
server.mock({ path: '/my-endpoint' });
Will throw an error with the following message:
Request matching {
"method": "GET",
"path": "/my-endpoint"
} already mocked
The path
is the only required property when defining the request shape.
server.mock({ path: '/my-endpoint' });
Providing a method
will match only requests using that method. If no method
is specified and the request has a body (see below) then the method defaults to
POST, otherwise it defaults to GET.
server.mock({ path: '/my-endpoint', method: 'DELETE' });
The method
string is case-insensitive.
Supported methods are GET
, POST
, PUT
, DELETE
and HEAD
.
Multiple mocks defined on the same endpoint with different methods are treated as independent mocks.
Query strings can be mocked in 2 ways; either by adding the query string to the
path field or by providing a separate object on the query
field.
server.mock({ path: '/my-endpoint?page=1&perPage=20' });
or
server.mock({ path: '/my-endpoint', query: { page: '1', perPage: '20' } });
In the second style, the object values should always be specified as strings.
If no query string is specified in the mock then any request to that endpoint will match, regardless of the query string.
Request bodies can be mocked by providing the body
property. Deeply nested
object structures will be matched recursively.
server.mock({ path: '/my-endpoint', body: { foo: 'bar' } });
The data types of the mock and the request fields need to match exactly. This is by design, as many real servers are sensitive to this.
If a request body is specified but with no method
, the method will default to
POST.
If no request body is specified in the mock then any request to that endpoint using that method will match, regardless of the request body.
Request headers can be mocked by providing the headers
property with header
type and value being object properties and values respectively.
server.mock({ path: '/my-endpoint', headers: { 'X-Foo', 'bar' } });
Requests will be handled if all the headers specified in the mock match. Any other headers on the request will match, regardless of the headers.
Customise the response for a particular mock by passing an object as the second
argument to mock
to define the response shape.
The response argument is optional. If no response is provided the mock will
return a 200
status with an empty body.
The response status can be set by providing a status
property.
server.mock({ path: '/my-endpoint' }, { status: 201 });
If no status is specified the response will default to 200
.
The response body can be set by providing a body
property.
server.mock({ path: '/my-endpoint' }, { body: { foo: 'bar' } });
The response headers can be set by providing a headers
property which should
be an object with header type and value being object properties and values
respectively.
server.mock({ path: '/my-endpoint' }, { headers: { 'x-foo': 'bar' } });
The response will always contain the specified headers but may also contain additional headers automatically added by the server.
All mocks and requests are logged by the server which provides easy access to this information in a format similar to the way mocks are defined. This structure is intended to make adding and adjusting mocks easier.
To get any requests that were not handled by a mock, call
getUnhandledRequests
.
server.getUnhandledRequests();
This will return an array of requests in the order that they occurred. For example:
[
{
"request": {
"path": "/my-endpoint",
"method": "GET"
}
},
]
To get requests that were handled by mocks including what response was returned,
call getHandledRequests
.
server.getHandledRequests();
This will return an array of requests and responses in the order that they occurred. For example:
[
{
"request": {
"path": "/my-endpoint",
"method": "GET"
},
"response": {
"status": 200
}
}
]
To get a list of any mocks that have not been called, call getUncalledMocks
.
server.getUncalledMocks();
This will return an array of uncalled mocks in the order that they were defined. For example:
[
{
"request": {
"path": "GET",
"method": "/endpoint"
},
"response": {
"status": 200
}
}
]
In some situations it maybe useful to be able to proxy requests that aren't mocked to a real server.
server.start(9001, 'http://realserver.com');
When a request is proxied the mock server will return the response exactly as it was returned by the real server.
Both the request and the response are recorded and are available via the
getProxiedRequests
method.
server.getProxiedRequests();
Any mocks that match will be handled first and those requests won't be proxied. This allows for selective mocking of APIs.
localhost
This library was inspired and influenced by:
FAQs
API mocking library that runs as a real HTTP server
The npm package @teamjourney/api-mock-server receives a total of 212 weekly downloads. As such, @teamjourney/api-mock-server popularity was classified as not popular.
We found that @teamjourney/api-mock-server demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Four npm packages disguised as cryptographic tools steal developer credentials and send them to attacker-controlled Telegram infrastructure.
Security News
Ruby maintainers from Bundler and rbenv teams are building rv to bring Python uv's speed and unified tooling approach to Ruby development.
Security News
Following last week’s supply chain attack, Nx published findings on the GitHub Actions exploit and moved npm publishing to Trusted Publishers.