typescript interface extends mock

848 Views Asked by At

I have a typescript interface cRequest that's being passed as a type in a class method. This interface also extends express Request type. What's the correct way to mock this in jest or typemoq?

import { Request } from 'express';
import { User } from '.';
export interface cRequest extends Request {
    context: {
        ID?: string;
        user?: string;
        nonUser?: string;
    };
    user?: User;
}
export default cRequest;

This is being used in a class method as follows

import { Response } from 'express';
public getData = async (req: cRequest, res: Response) => {}

And if i try to test it as follows it fails

const expRespMock: TypeMoq.IMock<Response> = TypeMoq.Mock.ofType<Response>();
const cReqMock: TypeMoq.IMock<cRequest> = TypeMoq.Mock.ofType<cRequest>();
await classObj.getData(cReqMock, expRespMock);

with the following message

  Argument of type 'IMock<cRequest>' is not assignable to parameter of type 'cRequest'.
  Property 'context' is missing in type 'IMock<cRequest>'.

What's the correct way to inject this interface mock into the method in tests?

2

There are 2 best solutions below

1
felixmosh On

Why to invent the wheel? Jest has an interface that "decorates" given interface with the additional methods.

For example:

interface IRequest {
   req: string;
}

requestMock: jest.Mocked<IRequest>;

requestMock will have the IRequest interface + the mocks interface.

The simplest way to learn about new jest types is to check the source-code of the @types/jest lib, for example I've checked that is the return type of jest.spyOn and from that I've learned about jest.Mocked<>.

0
meteor On

I was able to overcome this problem as follows

const cRequestStub= <cRequest> {};

And also it's now possible to selectively inject params as i need without any errors

const cRequestStub= <cRequest> {user: undefined}; or
const cRequestStub= <cRequest> {context: {ID: '', user: '', nonUser: ''}};

await classObj.getData(cRequestStub, expRespMock);