Simple express mock server with a flexible API inspired by fetch-mock
# npm
npm install -D mocaron
# yarn
yarn add -D mocaron
# pnpm
pnpm add -D mocaronimport { MockServer } from "mocaron";
const mockServer = new MockServer({ port: 3000 });
await mockServer.start();
mockServer.get("/test", { status: 200, body: { message: "Hello World" } });
const response = await fetch("http://localhost:3000/test");
console.log(response.status); // 200
console.log(await response.json()); // { message: "Hello World" }
await mockServer.stop();See constructor() start() stop()
import { MockServer } from "mocaron";
const mockServer = new MockServer({ port: 3000 });
await mockServer.start();
// ...
await mockServer.stop();Register a mock using mock().
mockServer.mock(
{ path: "/test", method: "GET" },
{ status: 200, body: { message: "Hello World" } },
);
const response = await fetch("http://localhost:3000/test");
console.log(response.status); // 200
console.log(await response.json()); // { message: "Hello World" }You can also register mocks that only match a specific HTTP method.
See get() post() put() patch() delete()
mockServer
.get("/test", { status: 200, body: { message: "Hello World" } })
.post("/test", { status: 201, body: { message: "Created" } })
.put("/test", { status: 200, body: { message: "Replaced" } })
.patch("/test", { status: 200, body: { message: "Updated" } })
.delete("/test", { status: 204 });If a request does not match any of the registered mocks the server will respond with a 404 status code.
const response = await fetch("http://localhost:3000/test");
console.log(response.status); // 404If two or more mocks match the same request the server will respond with a 404 status code.
mockServer.mock({ path: "/foo" }, "foo").mock({ path: "/foo" }, "bar");
const response = await fetch("http://localhost:3000/foo");
console.log(response.status); // 404You can override this behavior by passing the overwrite option to the last matching mock.
mockServer
.mock({ path: "/foo" }, "foo")
.mock({ path: "/foo" }, "bar", { overwrite: true });
const response = await fetch("http://localhost:3000/foo");
console.log(response.status); // 200
console.log(await response.text()); // barCalling reset() will reset the mock server to its initial state.
mockServer.get("/test", { status: 200 });
let response = await fetch("http://localhost:3000/test");
console.log(response.status); // 200
mockServer.reset();
response = await fetch("http://localhost:3000/test");
console.log(response.status); // 404Set up the mock server for each test using start(), stop() and reset().
import { MockServer } from "mocaron";
import { beforeAll, afterAll, beforeEach, test, assert } from "my-test-library";
const mockServer = new MockServer({ port: 3000 });
beforeAll(() => mockServer.start());
afterAll(() => mockServer.stop());
beforeEach(() => mockServer.reset());Test that a mock has been called using hasBeenCalledWith().
test("mock has been called", async () => {
mockServer.get("/test", { status: 200 });
await fetch("http://localhost:3000/test");
assert(mockServer.hasBeenCalledWith({ path: "/test" }));
});Test that a mock has been called a specific number of times using hasBeenCalledTimes().
test("mock has been called 3 times", async () => {
mockServer.get("/test", { status: 200 });
await fetch("http://localhost:3000/test");
await fetch("http://localhost:3000/test");
await fetch("http://localhost:3000/test");
assert(mockServer.hasBeenCalledTimes(3, { path: "/test" }));
});Custom assertions using calls().
test("custom assertion", async () => {
mockServer.get("/test", { status: 200 });
await fetch("http://localhost:3000/test");
assert(mockServer.calls().length === 1);
assert(mockServer.calls()[0].request.path === "/test");
});MockServerExpectationMessageOptionsRequestMatcherMatcherObjMatcherFnResponseResponseObjResponseFnMockOptionsMockCall
Create a new MockServer instance.
| Param | Type | Default |
|---|---|---|
| options | Options |
- |
const mockServer = new MockServer({ port: 3000 });Start the mock server.
await mockServer.start();Stop the mock server.
await mockServer.stop();Get the port the mock server is running on.
const port = mockServer.port();
console.log(port); // 3000Register a mock.
| Param | Type | Default |
|---|---|---|
| matcher | string | RegExp | Matcher |
- |
| response | string | number | Response |
- |
| options | MockOptions |
{} |
If matcher is a string or RegExp, it will be used to match the request path.
If response is a string, it will be used as the response body.
If response is a number, it will be used as the response status code.
Returns the MockServer instance.
mockServer.mock({ path: "/test" }, { status: 204 });
const response = await fetch("http://localhost:3000/test");
console.log(response.status); // 204Register a mock that only responds to requests using the HTTP GET method.
| Param | Type | Default |
|---|---|---|
| matcher | string | RegExp | MatcherObj |
- |
| response | string | number | Response |
- |
| options | MockOptions |
{} |
If matcher is a string or RegExp, it will be used to match the request path.
If response is a string, it will be used as the response body.
If response is a number, it will be used as the response status code.
Returns the MockServer instance.
mockServer.get("/test", {
status: 200,
body: { message: "Hello World" },
});
const response = await fetch("http://localhost:3000/test");
console.log(response.status); // 200
console.log(await response.json()); // { message: "Hello World" }Register a mock that only responds to requests using the HTTP POST method.
| Param | Type | Default |
|---|---|---|
| matcher | string | RegExp | MatcherObj |
- |
| response | string | number | Response |
- |
| options | MockOptions |
{} |
If matcher is a string or RegExp, it will be used to match the request path.
If response is a string, it will be used as the response body.
If response is a number, it will be used as the response status code.
Returns the MockServer instance.
mockServer.post("/test", {
status: 201,
body: { message: "Hello World" },
});
const response = await fetch("http://localhost:3000/test", {
method: "POST",
body: JSON.stringify({ message: "Hello World" }),
});
console.log(response.status); // 201
console.log(await response.json()); // { message: "Hello World" }Register a mock that only responds to requests using the HTTP PUT method.
| Param | Type | Default |
|---|---|---|
| matcher | string | RegExp | MatcherObj |
- |
| response | string | number | Response |
- |
| options | MockOptions |
{} |
If matcher is a string or RegExp, it will be used to match the request path.
If response is a string, it will be used as the response body.
If response is a number, it will be used as the response status code.
Returns the MockServer instance.
mockServer.put("/test", {
status: 200,
body: { message: "Hello World" },
});
const response = await fetch("http://localhost:3000/test", {
method: "PUT",
body: JSON.stringify({ message: "Hello World" }),
});
console.log(response.status); // 200
console.log(await response.json()); // { message: "Hello World" }Register a mock that only responds to requests using the HTTP PATCH method.
| Param | Type | Default |
|---|---|---|
| matcher | string | RegExp | MatcherObj |
- |
| response | string | number | Response |
- |
| options | MockOptions |
{} |
If matcher is a string or RegExp, it will be used to match the request path.
If response is a string, it will be used as the response body.
If response is a number, it will be used as the response status code.
Returns the MockServer instance.
mockServer.patch("/test", {
status: 200,
body: { message: "Hello World" },
});
const response = await fetch("http://localhost:3000/test", {
method: "PATCH",
body: JSON.stringify({ message: "Hello World" }),
});
console.log(response.status); // 200
console.log(await response.json()); // { message: "Hello World" }Register a mock that only responds to requests using the HTTP DELETE method.
| Param | Type | Default |
|---|---|---|
| matcher | string | RegExp | MatcherObj |
- |
| response | string | number | Response |
- |
| options | MockOptions |
{} |
If matcher is a string or RegExp, it will be used to match the request path.
If response is a string, it will be used as the response body.
If response is a number, it will be used as the response status code.
Returns the MockServer instance.
mockServer.delete("/test", { status: 204 });
const response = await fetch("http://localhost:3000/test", {
method: "DELETE",
});
console.log(response.status); // 204Get all registered mocks.
Returns an array of Mock objects.
mockServer.mock({ path: "/test" }, { status: 204 });
const mocks = mockServer.mocks();
console.log(mocks);
// [{ matcher: { path: "/test" }, response: { status: 204 } }]Get all registered calls.
Returns an array of Call objects.
mockServer.mock({ path: "/test" }, { status: 204 });
await fetch("http://localhost:3000/test");
const calls = mockServer.calls();
console.log(calls);
// [{ matcher: { path: "/test" }, request: <express.Request> }]Check if the route has been called with the given matcher.
| Param | Type | Default |
|---|---|---|
| matcher | string | RegExp | Matcher |
- |
If matcher is a string or RegExp, it will be used to match the request path.
Returns true if the route has been called with the given matcher, false otherwise.
mockServer.get("/test", { status: 200 });
console.log(mockServer.hasBeenCalledWith({ path: "/test" })); // false
await fetch("http://localhost:3000/test");
console.log(mockServer.hasBeenCalledWith({ path: "/test" })); // trueCheck if the route has been called a certain number of times with the given matcher.
| Param | Type | Default |
|---|---|---|
| times | number |
- |
| matcher | string | RegExp | Matcher |
- |
If matcher is a string or RegExp, it will be used to match the request path.
Returns true if the route has been called times times with the given matcher, false otherwise.
mockServer.get("/test", { status: 200 });
console.log(mockServer.hasBeenCalledTimes(0, { path: "/test" })); // true
console.log(mockServer.hasBeenCalledTimes(1, { path: "/test" })); // false
await fetch("http://localhost:3000/test");
console.log(mockServer.hasBeenCalledTimes(0, { path: "/test" })); // false
console.log(mockServer.hasBeenCalledTimes(1, { path: "/test" })); // trueCount the number of times the server was called with the given matcher.
| Param | Type | Default |
|---|---|---|
| matcher | string | RegExp | Matcher |
- |
If matcher is a string or RegExp, it will be used to match the request path.
Returns the number of times the server has been called with the given matcher.
mockServer.get("/test", { status: 200 });
console.log(mockServer.countCalls({ path: "/test" })); // 0
await fetch("http://localhost:3000/test");
console.log(mockServer.countCalls({ path: "/test" })); // 1Reset all mocks and calls.
mockServer.get("/test", { status: 200 });
await fetch("http://localhost:3000/test");
console.log(mockServer.mocks());
// [{ matcher: { path: "/test", method: "GET" }, response: { status: 200 } }]
console.log(mockServer.calls());
// [{ matcher: { path: "/test", method: "GET" }, request: <express.Request> }]
mockServer.reset();
console.log(mockServer.mocks()); // []
console.log(mockServer.calls()); // []Reset all mocks.
mockServer.get("/test", { status: 200 });
console.log(mockServer.mocks());
// [{ matcher: { path: "/test", method: "GET" }, response: { status: 200 } }]
mockServer.resetMocks();
console.log(mockServer.mocks()); // []Reset all calls.
mockServer.get("/test", { status: 200 });
await fetch("http://localhost:3000/test");
console.log(mockServer.calls());
// [{ matcher: { path: "/test", method: "GET" }, request: <express.Request> }]
mockServer.resetCalls();
console.log(mockServer.calls()); // []Format an expectation message for hasBeenCalledWith().
| Param | Type | Default |
|---|---|---|
| mockServer | MockServer |
- |
| matcher | Matcher |
- |
Returns a string with the formatted expectation message.
if (!mockServer.hasBeenCalledWith(matcher)) {
throw new Error(ExpectationMessage.hasBeenCalledWith(mockServer, matcher));
}Format an expectation message for hasBeenCalledTimes().
| Param | Type | Default |
|---|---|---|
| mockServer | MockServer |
- |
| times | number | - |
| matcher | Matcher |
- |
Returns a string with the formatted expectation message.
if (!mockServer.hasBeenCalledTimes(mockServer, 2, matcher)) {
throw new Error(
ExpectationMessage.hasBeenCalledTimes(mockServer, 2, matcher),
);
}Object with the following properties:
| Property | Type | Description |
|---|---|---|
| port | number |
port to run the mock server on |
Type alias for express.Request with the body property typed as Buffer | undefined.
type Request = express.Request<{}, unknown, Buffer | undefined>;Type alias for MatcherObj | MatcherFn.
type Matcher = MatcherObj | MatcherFn;Object with the following properties:
| Property | Type | Description |
|---|---|---|
| method | string | undefined |
HTTP method to match against |
| path | string | RegExp | undefined |
path to match against |
| query | Request["query"] | undefined |
query parameters to match against. Parameters explicitly set to undefined will not match when provided. |
| headers | Record<string, string | undefined> | undefined |
headers to match against. Headers explicitly set to undefined will not match when provided. |
| body | string | object | undefined |
body to match against. If an object is given it will be compared to the request body parsed as JSON. |
Function that takes a Request and returns whether the request should match.
type MatcherFn = (req: Request) => boolean;Type alias for ResponseObj | ResponseFn.
type Response = ResponseObj | ResponseFn;Object with the following properties:
| Property | Type | Description |
|---|---|---|
| status | number | undefined |
status code to respond with (defaults to 200) |
| headers | Record<string, string> | undefined |
headers to respond with |
| body | string | object | undefined |
body to respond with. If an object is given it will be converted to a JSON string. |
| delay | number | undefined |
delay in milliseconds before responding |
Function or async function that takes a Request and returns a ResponseObj.
type ResponseFn = (req: Request) => ResponseObj | Promise<ResponseObj>;Object with the following properties:
| Property | Type | Description |
|---|---|---|
| overwrite | boolean | undefined |
when set to true,previous ambiguous mocks matching the same request will be overwritten |
Object with the following properties:
| Property | Type | Description |
|---|---|---|
| matcher | Matcher |
matcher to match against the request |
| response | Response |
response the server will respond with when matched |
| options | MockOptions |
see MockOptions |
Object with the following properties:
| Property | Type | Description |
|---|---|---|
| request | Request |
request the server was called with |
| matcher | Matcher |
matcher the request matched against |