Express Middleware Testing Helper

raw JSON →
1.7.0 verified Thu Apr 23 auth: no javascript maintenance

reqresnext is a minimalist utility designed for testing Express.js middleware. It provides mock implementations of the `req`, `res`, and `next` objects, allowing developers to isolate and test middleware functions without a full Express server setup. The current stable version is 1.7.0, released in February 2022. Releases are infrequent, primarily focusing on bug fixes and minor enhancements rather than new features. Its key differentiator is its small footprint and focused scope, aiming to provide just enough mocking capability for unit testing, contrasting with more comprehensive HTTP mocking libraries that might offer broader server-side simulation. It ships with robust TypeScript type definitions, making it well-suited for modern JavaScript and TypeScript projects that prioritize type safety in their testing environments.

error Property 'user' does not exist on type 'MockRequest'.
cause Attempting to assign or access custom properties on the mocked request object without explicit type assertion or declaration merging in TypeScript, leading to type errors.
fix
When adding custom properties (e.g., from an authentication middleware), either use (req as any).user = ... for quick fixes or extend the MockRequest interface via TypeScript declaration merging (declare module 'reqresnext' { interface MockRequest { user?: { id: number; name: string; }; } }) for better type safety.
error TypeError: Cannot read properties of undefined (reading 'authorization')
cause Accessing `req.headers.authorization` when `req.headers` was not initialized or the `authorization` property was not provided in the `mockReq` options.
fix
Ensure req.headers and any specific header properties are provided in the mockReq options when creating the mock request: mockReq({ headers: { authorization: 'Bearer token' } }).
error expect(next).toHaveBeenCalled() fails but middleware appears to call next()
cause The `next` function mock might not be correctly recognized by your testing framework, or the middleware's logic is not calling `next()` under the specific test conditions you've set up.
fix
Verify that mockNext() is being used, as it returns a Jest-compatible mock function by default. Double-check your middleware's conditional logic to ensure next() is indeed invoked when expected, and that no early return or res.send() prevents its execution.
gotcha Prior to `v1.7.0`, incoming request headers might not have been consistently lowercased, which is standard behavior for HTTP headers. Middleware relying on specific header casing might have behaved unexpectedly.
fix Upgrade to `v1.7.0` or later. Ensure your middleware accesses headers using lowercase keys (e.g., `req.headers['content-type']`).
gotcha In versions prior to `v1.6.5`, the `res.end()` mock might not have correctly concatenated the response body across multiple calls, potentially leading to incomplete or incorrect response content in tests.
fix Upgrade to `v1.6.5` or later to ensure `res.end()` behavior correctly accumulates the response body.
gotcha While `reqresnext` provides robust mocks for Express middleware testing, the mock objects are not full replicas of native Node.js `http.IncomingMessage` and `http.ServerResponse` objects. Certain advanced features, event emitters, or stream manipulations might not be fully supported.
fix For complex scenarios involving streaming or low-level HTTP features, consider integration tests with a real Express server or a more comprehensive HTTP mocking library if `reqresnext` proves insufficient.
gotcha TypeScript users should be aware that casting `MockRequest` and `MockResponse` to `express.Request` and `express.Response` might be necessary when passing them to middleware functions, as the types are not directly compatible without explicit assertion due to potential interface differences.
fix Use type assertions like `req as unknown as Request` or `res as unknown as Response` when calling middleware with `reqresnext` mock objects, especially if your middleware is strictly typed.
npm install reqresnext
yarn add reqresnext
pnpm add reqresnext

Demonstrates how to mock `req`, `res`, and `next` objects and unit test an Express middleware function using Jest expectations.

import { mockReq, mockRes, mockNext } from 'reqresnext';
import { Request, Response, NextFunction } from 'express';

// Example Express middleware
const authMiddleware = (req: Request, res: Response, next: NextFunction) => {
  if (req.headers && req.headers.authorization === 'Bearer my-secret-token') {
    // In a real app, you might decode a JWT and set req.user
    (req as any).user = { id: 1, name: 'Test User' }; 
    next();
  } else {
    res.status(401).send('Unauthorized');
  }
};

// Basic test using a common testing framework like Jest
describe('authMiddleware', () => {
  it('should allow access with a valid token', () => {
    const req = mockReq({ headers: { authorization: 'Bearer my-secret-token' } });
    const res = mockRes();
    const next = mockNext();

    authMiddleware(req as unknown as Request, res as unknown as Response, next);

    expect(next).toHaveBeenCalledTimes(1);
    expect((req as any).user).toEqual({ id: 1, name: 'Test User' });
    expect(res.statusCode).toBe(200); // Default status if next() is called
    expect(res.send).not.toHaveBeenCalled();
  });

  it('should deny access without a token', () => {
    const req = mockReq(); // No authorization header
    const res = mockRes();
    const next = mockNext();

    authMiddleware(req as unknown as Request, res as unknown as Response, next);

    expect(next).not.toHaveBeenCalled();
    expect(res.statusCode).toBe(401);
    expect(res.send).toHaveBeenCalledWith('Unauthorized');
  });
});