Mocking classes in Jest / Typescript
Ben Mitchinson
Posted on October 18, 2021
Cross posted on my website mitchinson.dev
TL;DR
GetANumber.test.ts mocks a class, and further customizes a class method on that mocked class for a single test.
Purpose
It was surprisingly hard to find a recently written article about the fastest way to setup Jest with some simple class mocks in Typescript. The following example demonstrates mocking a class and modifying methods of that mocked class within a single test.
Libraries like jest-ts-auto-mock are not used, cause I was unable to find a way to get them to work. Could have just been using them wrong but who knows.
I used the following methods to mock classes in an Express app while coding in test driven development.
Explanation
Comments are all over in this Example Repo, but some highlights are:
-
jest.mock
ends up at the top of the file when it's transpiled.- Even if you put it under other things, it gets pulled to the top.
///////////////////
jest.mock("./Class", mockOne);
it("does a thing", () => {
expect(class).toBe(one)
})
it("does another thing", () => {
jest.mock("./Class", mockTwo);
expect(class).toBe(two)
})
///////////////////
// is really
///////////////////
jest.mock("./Class", mockOne); // this mock is useless
jest.mock("./Class", mockTwo); // as it's immediately replaced
it("does a thing", () => {
expect(class).toBe(one)
})
it("does another thing", () => {
expect(class).toBe(two)
})
///////////////////
// You might as well always write `.mock` calls at the top of your file.
- The example mocks a class that's a default export. Named exports can also be mocked by nesting the class mockImplementation one layer deeper.
-
jest.mock('{path_to_custom_class}')
will replace that paths default export in the runtime with the defined mock in__mocks__
dir defined at the same level. - If you'd like to modify a mock / assert things that happened to a mock, you need to import them from the "real" class.
- Never manually import from
__mocks__
, get the exports of__mocks__
"through" a normal import.
- Never manually import from
import * as MockNumberGen from "./__mocks__/NumberGen";
import * as NumberGen from "./NumberGen"; // __mocks__/CVEPathData
// Give me the mock class i've defined in __mocks__/{classname} and let me
// name it mock{ClassName}Constructor
// Give me the mock function i've defined in __mocks__/{classname}
const { default: mockNumberGenConstructor, mockGetOne } =
// Get these things from the NumberGen class, because I know that jest
// has secretly replaced it with the contents of MockNumberGen
NumberGen as unknown as typeof MockNumberGen;
// Tell typescript that these things are really coming from MockNumberGen,
// so it should type them as such
The full test is available here
Posted on October 18, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.