Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mocking/Stubbing a Typescript interface with jest

Is it possible to mock or stub a Typescript interface via Jest or another mocking/stubbing library?

For example I'd like to mock ExpressJS's Response object: export interface Response extends http.ServerResponse, Express.Response

Rather than handcrafting an object that implements all the methods I'm looking for a library to do that for me.

like image 889
n00b Avatar asked Feb 04 '19 04:02

n00b


2 Answers

I ended up using type assertion for it which is a bit of a hack. So something like:

const res = {} as Express.Response;

Some information about type assertions is available here which says:

Type assertions are a way to tell the compiler “trust me, I know what I’m doing.” A type assertion is like a type cast in other languages, but performs no special checking or restructuring of data. It has no runtime impact, and is used purely by the compiler. TypeScript assumes that you, the programmer, have performed any special checks that you need.

like image 72
n00b Avatar answered Sep 20 '22 15:09

n00b


With inspiration from @n00b but more completely:

Use a type assertion first to unknown then to the interface you want in order to make the compiler accept it.

Then mock the things you need (in this example, myFunction only calls Response.send, you will need to mock more or less)

A complete example, this can be in a __tests__/myFunctionTest.ts file:

import * as functions from 'firebase-functions';
import * as myfunction from '../src/myFunction';
test('it should do the thing', () => {
  const req = { } as unknown;
  const mockReq = req as functions.https.Request;
  const res = { send: jest.fn() } as unknown;
  const mockRes = res as functions.Response;
  myFunction.doTheThing(mockReq, mockRes);
  expect(mockRes.send).toBeCalledWith("{ 'status': 'the thing is done' }";
});

The src/myFunction.ts file would be:

import * as functions from 'firebase-functions';

export const doTheThing = functions.https.onRequest((request, response) => {
  response.send("{ 'status': 'the thing is done' }");
});

Note this is very very close to the mock you need for Express - the firebase functions request / response are built on those Typescript interfaces so the strategy should apply.

like image 35
Mike Hardy Avatar answered Sep 19 '22 15:09

Mike Hardy