2022.12.17

2022.12 Vol.1

A little bit of type extension

Mocking in NodeJS

NodeJS version 19 added basic mocking support to the built in test runner standard library node:test. We are already using the node test runner in our stack and would rather use this mocking implementation instead of introducing another third-party dependency like sinon.

The Definitely Typed repository handles defining types for node’s standard library. But it looks like they are fairly conservative about when they define types for new features, like this mocking support. This is a little at odds with the new quick release cycle node has adopted (e.g. in nine months v18 will be the oldest version receiving security updates).

We also only use node to build and test code, we don’t use the runtime in production. We don’t have a reason to wait for the new features. So for the time being, I defined types for a subset of node’s new mocking capabilities:

import "node:test"; // trigger declaration merging

declare module "node:test" {
  export const mock: MockTracker;

  interface MockFnOptions {
    times: number;
  }

  // https://nodejs.org/api/test.html#class-mocktracker
  interface MockTracker {
    fn<T>(
      original?: T,
      implementation?: T,
      options?: MockFnOptions,
    ): T & { mock: MockFunctionContext };
    reset: () => void;
    restoreAll: () => void;
  }

  // https://nodejs.org/api/test.html#class-mockfunctioncontext
  interface MockFunctionContext {
    callCount: () => number;
  }
}

@types/node.d.ts extending the @types/node test runner module with a subset of mocking support.

#javascript