Breno Calazans

How to use TypeScript and Jest mocks

2019-07-101 Min Read — In Jest, TypeScript

It's pretty common to mock modules in Jest. When using TypeScript that might be a bit harder because they are not automatically resolved by TypeScript.

Let's say we are using a function useFooContext from a module called foo:

1// foo.d.ts
2declare module "foo" {
3 interface FooContext {
4 bar: number;
5 }
6
7 export function useFooContext(): FooContext;
8}

So we create a mock of the module foo in the __mocks__ folder:

1// __mocks__/foo.ts
2export const useFooContext = jest.fn(() => {});

And finally, create our test file using mocked foo:

1// index.test.ts
2import { useFooContext } from "foo";
3
4test("sample test", () => {
5 // Error: Property 'mockImplementation' does not exist on type '() => FooContext'.ts(2339)
6 useFooContext.mockImplementation(() => {
7 bar: 123;
8 });
9
10 const context = useFooContext();
11
12 expect(context.bar).toBe(123);
13});

Property 'mockImplementation' does not exist on type '() => FooContext'.ts(2339)

TypeScript throws an error since it doesn't resolve mock files as Jest does. It expects useFooContext to have the type defined in its definition.

Solution

We should hint TypeScript that the function imported is in fact a jest mock function.

1import {
2 useFooContext,
3 FooContext // Get the type returned by `useFooContext`
4} from "foo";
5
6// Create a new variable and type it as jest.Mock passing the type
7const mockedUseFooContext = useFooContext as jest.Mock<FooContext>;
8
9test("sample test", () => {
10 // TypeScript will type check the value returned by the mock implementation 💯
11 mockedUseFooContext.mockImplementation(() => {
12 bar: "mocked return for this test";
13 });
14
15 const context = mockedUseFooContext();
16
17 expect(context.bar).toBe(123);
18});

I hope that's helpful!

Discuss on TwitterEdit post on GitHub