Mock dependency in Jest with TypeScript Mock dependency in Jest with TypeScript javascript javascript

Mock dependency in Jest with TypeScript


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 instanceTestedClassDependency can be either class or type or interface


Use the mocked helper from ts-jestlike explained here

// foo.spec.tsimport { mocked } from 'ts-jest/utils'import { foo } from './foo'jest.mock('./foo')// here the whole foo var is mocked deeplyconst mockedFoo = mocked(foo, true)test('deep', () => {  // there will be no TS error here, and you'll have completion in modern IDEs  mockedFoo.a.b.c.hello('me')  // same here  expect(mockedFoo.a.b.c.hello.mock.calls).toHaveLength(1)})test('direct', () => {  foo.name()  // here only foo.name is mocked (or its methods if it's an object)  expect(mocked(foo.name).mock.calls).toHaveLength(1)})


There are two solutions tested for TypeScript version 3.x and 4.x, both are casting desired function

1) Use jest.MockedFunction

import * as dep from './dependency';jest.mock('./dependency');const mockMyFunction = dep.myFunction as jest.MockedFunction<typeof dep.myFunction>;

2) Use jest.Mock

import * as dep from './dependency';jest.mock('./dependency');const mockMyFunction = dep.default as jest.Mock;

There is no difference between these two solutions. The second one is shorter and I would therefore suggest using that one.

Both casting solutions allows to call any jest mock function on mockMyFunction like mockReturnValue or mockResolvedValuehttps://jestjs.io/docs/en/mock-function-api.html

mockMyFunction.mockReturnValue('value');

mockMyFunction can be used normally for expect

expect(mockMyFunction).toHaveBeenCalledTimes(1);