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 mocaron
import { 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); // 404
If 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); // 404
You 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()); // bar
Calling 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); // 404
Set 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");
});
MockServer
ExpectationMessage
Options
Request
Matcher
MatcherObj
MatcherFn
Response
ResponseObj
ResponseFn
MockOptions
Mock
Call
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); // 3000
Register 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); // 204
Register 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); // 204
Get 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" })); // true
Check 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" })); // true
Count 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" })); // 1
Reset 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 |