Mocking Express Request with Jest and Typescript using correct types

Your mock data type doesn't have to perfectly fit the actual data. Well, it doesn't by definition. It's just a mock, right?

What you need is a type assertion. It's a way to tell TypeScript "Okay bro, I know what I'm doing here.".

This is not a production code, it's a test. You're probably even running it in watch mode. We can reject some type safety here without problem. TypeScript doesn't know it's a mock, but we do.

const mockRequest = {
    body: {
    firstName: 'J',
    lastName: 'Doe',
    email: '[email protected]',
    password: 'Abcd1234',
    passwordConfirm: 'Abcd1234',
    company: 'ABC Inc.',
    },
} as Request;

If something crashes during the test, because mockRequest isn't similar to Request enough, we'll know and we'll fix the mock, add some new properties etc.

If as Request doesn't work you can tell TypeScript "I REALLY know what I'm doing here" by asserting to any or unknown first and then to the type you need. It would look like

const x: number = "not a number :wink:" as any as number;

It's useful when we'd like to test that our code doesn't work well with bad input.

For your particular case -- mocking express Request -- there is jest-express to help you, if you can spare the node_modules size of course.


For future search about this theme, I recommend seeing this library: https://www.npmjs.com/package/node-mocks-http

This library has methods to create mocked objects for Request and Response of the Express Framework, which helped me a lot and was the easy way I found.

Simple unit test example:

import { Request, Response } from 'express';
import {
  createRequest, createResponse, MockRequest, MockResponse,
} from 'node-mocks-http';
import { AppController } from './app-controller';
import { APP_NAME, APP_VERSION } from '../../constants';

describe('AppController - UnitTestCase', () => {
  let controller: AppController;
  let request: MockRequest<Request>;
  let response: MockResponse<Response>;
  beforeEach(() => {
    controller = new AppController();
    /** Response Mock */
    response = createResponse();
  });

  it('should be defined', () => {
    expect(controller).toBeDefined();
  });

  describe('GET /', () => {
    it('should return 200 and API Name + API Version', (done) => {
      /** Request Mock */
      request = createRequest({
        method: 'GET',
        url: '/',
      });

      AppController.index(request, response);

      const body = { app: `${APP_NAME}:${APP_VERSION}` };
      const result = response._getJSONData();
      expect(result).toMatchObject(body);
      expect(result.app).toEqual(body.app);
      expect(response.getHeaders()).toHaveProperty('content-type');
      console.log('headers', response.getHeaders());
      console.log('response body', result);
      done();
    });
  });
});