Node HTTP Mocks
node-mocks-http is a testing utility for Node.js environments that provides mock implementations of `http.IncomingMessage` (request) and `http.ServerResponse` (response) objects. It is designed to facilitate unit testing of web server applications, particularly those built with frameworks like Express, Next.js, and Koa, by allowing developers to simulate HTTP requests and responses without needing to spin up a full HTTP server. The current stable version is 1.17.2, and the project shows a positive release cadence with recent updates. Key differentiators include its focus on low-level `http` object mocking, bundled TypeScript typings, and explicit support for framework-specific request/response types (e.g., Express, Next.js API routes, Next.js App Router). This makes it suitable for isolating and testing individual route handlers or middleware functions efficiently.
Common errors
-
TypeError: httpMocks.createRequest is not a function
cause Attempting to destructure `createRequest` or `createResponse` directly from the package, or using CommonJS `require` in an ESM context (or vice-versa) incorrectly.fixEnsure you import `httpMocks` as a default export (`import httpMocks from 'node-mocks-http';` for ESM or `const httpMocks = require('node-mocks-http');` for CJS) and then call its methods: `httpMocks.createRequest()`. -
TS2345: Argument of type '{}' is not assignable to parameter of type 'Request'. Property 'body' is missing in type '{}' but required in type 'Request'.cause TypeScript error due to `createRequest` or `createResponse` being used without specifying the correct generic type, causing the mock object to default to `http.IncomingMessage` or `http.ServerResponse` which might not match the specific framework types (e.g., Express `Request`).fixAdd the correct generic type parameter to `createRequest` and `createResponse`, for example: `httpMocks.createRequest<express.Request>({...})` or `httpMocks.createResponse<express.Response>()`. Remember to import the `Request` and `Response` types from your framework (e.g., `import type { Request, Response } from 'express';`). -
response._getJSONData is not a function
cause The `_getJSONData()` (and similar `_getData()`, `_getHeaders()` etc.) methods are non-standard helper methods added by `node-mocks-http` for testing purposes, which might be called before the response stream has ended or if the response content is not JSON.fixEnsure that your route handler has called a method like `response.send()` or `response.end()` to complete the response before attempting to retrieve data. Also, `_getJSONData()` specifically expects JSON content.
Warnings
- gotcha When using TypeScript, remember to install the necessary `@types` packages (e.g., `@types/express`, `@types/node`). Although `node-mocks-http` ships with its own types, these peer dependencies are crucial for correctly typing the underlying framework interfaces your code expects.
- gotcha The mock `response` object's built-in event emitter is not fully functional and does not emit events by default. If your code under test relies on `response.on('event', ...)` for testing event handlers, you must provide your own event emitter instance to the mock response.
- gotcha When testing Next.js API routes or App Router handlers with TypeScript, ensure you import the specific `NextApiRequest`, `NextApiResponse`, `NextRequest`, or `NextResponse` types from the `next` package and use them as generics with `createRequest` and `createResponse`. By default, `node-mocks-http` mocks are Express-based.
- gotcha Node.js ESM (ECMAScript Modules) support in testing frameworks and mocking libraries can be complex. While `node-mocks-http` supports ESM imports for itself, mocking dependencies within ESM test files might require specific configurations or alternative tools like `testdouble` for module-level mocking.
Install
-
npm install node-mocks-http -
yarn add node-mocks-http -
pnpm add node-mocks-http
Imports
- httpMocks
const httpMocks = require('node-mocks-http');import httpMocks from 'node-mocks-http';
- httpMocks
const httpMocks = require('node-mocks-http'); - createRequest / createResponse
import { createRequest } from 'node-mocks-http';import httpMocks from 'node-mocks-http'; const request = httpMocks.createRequest();
- NextApiRequest / NextApiResponse
import { NextApiRequest } from 'node-mocks-http';import type { NextApiRequest, NextApiResponse } from 'next'; import httpMocks from 'node-mocks-http'; const mockRequest = httpMocks.createRequest<NextApiRequest>({});
Quickstart
import httpMocks from 'node-mocks-http';
import type { Request, Response } from 'express';
// Imagine this is your Express route handler
const routeHandler = function(request: Request, response: Response) {
const { id } = request.params;
if (id === '42') {
response.statusCode = 200;
response.setHeader('Content-Type', 'application/json');
response.send(JSON.stringify({
name: 'Bob Dog',
age: 42,
email: 'bob@dog.com'
}));
} else {
response.statusCode = 404;
response.send('User not found');
}
};
describe('routeHandler', () => {
it('should return user data for a valid ID', () => {
const request = httpMocks.createRequest<Request>({
method: 'GET',
url: '/user/42',
params: {
id: '42'
}
});
const response = httpMocks.createResponse<Response>();
routeHandler(request, response);
// Assertions using common test patterns (e.g., Jest/Chai style)
expect(response.statusCode).toBe(200);
expect(response._isEndCalled()).toBe(true);
expect(response._isJSON()).toBe(true);
expect(response._getData()).toEqual(JSON.stringify({
name: 'Bob Dog',
age: 42,
email: 'bob@dog.com'
}));
});
it('should return 404 for an invalid ID', () => {
const request = httpMocks.createRequest<Request>({
method: 'GET',
url: '/user/99',
params: {
id: '99'
}
});
const response = httpMocks.createResponse<Response>();
routeHandler(request, response);
expect(response.statusCode).toBe(404);
expect(response._isEndCalled()).toBe(true);
expect(response._getData()).toEqual('User not found');
});
});
// Minimal Jest-like environment for standalone execution
function describe(name: string, fn: () => void) {
console.log(`
${name}`);
fn();
}
function it(name: string, fn: () => void) {
process.stdout.write(` - ${name}...`);
try {
fn();
console.log(' ✅');
} catch (e: any) {
console.log(' ❌');
console.error(e.message);
}
}
const expect = (value: any) => ({
toBe: (expected: any) => {
if (value !== expected) throw new Error(`Expected ${value} to be ${expected}`);
},
toEqual: (expected: any) => {
if (JSON.stringify(value) !== JSON.stringify(expected)) throw new Error(`Expected ${JSON.stringify(value)} to equal ${JSON.stringify(expected)}`);
}
});