DEV Community

Ben Mitchinson
Ben Mitchinson

Posted on

4 1

Mocking classes in Jest / Typescript

Cross posted on my website mitchinson.dev

TL;DR

Example Test

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.
Enter fullscreen mode Exit fullscreen mode
  • 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.
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
Enter fullscreen mode Exit fullscreen mode

The full test is available here

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

Top comments (0)

AWS Security LIVE!

Join us for AWS Security LIVE!

Discover the future of cloud security. Tune in live for trends, tips, and solutions from AWS and AWS Partners.

Learn More

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay