Mock dependency in jest with typescript

Philip Chmalts picture Philip Chmalts · Feb 13, 2018 · Viewed 57.8k times · Source

When testing a module that has a dependency in a different file. When assigning that module to be jest.Mock typescript gives an error that the method mockReturnThisOnce(or any other jest.Mock method) does not exist on the dependency, this is because it is previously typed. What is the proper way to get typescript to inherit the types from jest.Mock?

Here is a quick example.

Dependency

const myDep = (name: string) => name;
export default myDep;

test.ts

import * as dep from '../depenendency';
jest.mock('../dependency');

it('should do what I need', () => {
  //this throws ts error
  // Property mockReturnValueOnce does not exist on type (name: string)....
  dep.default.mockReturnValueOnce('return')
}

I feel like this is a very common use case and not sure how to properly type this. Any help would be much appreciated!

Answer

Artur Górski picture Artur Górski · Sep 17, 2018

You can use type casting and your test.ts should look like this:

import * as dep from '../dependency';
jest.mock('../dependency');

const mockedDependency = <jest.Mock<typeof dep.default>>dep.default;

it('should do what I need', () => {
  //this throws ts error
  // Property mockReturnValueOnce does not exist on type (name: string)....
  mockedDependency.mockReturnValueOnce('return');
});

TS transpiler is not aware that jest.mock('../dependency'); changes type of dep thus you have to use type casting. As imported dep is not a type definition you have to get its type with typeof dep.default.

Here are some other useful patterns I've found during my work with Jest and TS

When imported element is a class then you don't have to use typeof for example:

import { SomeClass } from './SomeClass';

jest.mock('./SomeClass');

const mockedClass = <jest.Mock<SomeClass>>SomeClass;

This solution is also useful when you have to mock some node native modules:

import { existsSync } from 'fs';

jest.mock('fs');

const mockedExistsSync = <jest.Mock<typeof existsSync>>existsSync;

In case you don't want to use jest automatic mock and prefer create manual one

import TestedClass from './TestedClass';
import TestedClassDependency from './TestedClassDependency';

const testedClassDependencyMock = jest.fn<TestedClassDependency>(() => ({
  // implementation
}));

it('Should throw an error when calling playSomethingCool', () => {
  const testedClass = new TestedClass(testedClassDependencyMock());
});

testedClassDependencyMock() creates mocked object instance TestedClassDependency can be either class or type or interface