nodejs / help

:sparkles: Need help with Node.js? File an Issue here. :rocket:
1.44k stars 276 forks source link

How to mock named export using test runner #4295

Open tlan16 opened 7 months ago

tlan16 commented 7 months ago

Details

Hi, I'm trying out the new test runner from node. The intention is to remove dependency on jest and hopefully faster test execution.

I setup a proof of concept repo here: https://github.com/tlan16/node-typescript-app-template/tree/764d91f0cdfab0dcd4d2af5d5e9b04d6bcad5053

In the test here, I wanna mock the named export getWelcomeMessage to return a different value, but somehow not effective, aka test fails.

Node.js version

20.9.0

Example code

https://github.com/tlan16/node-typescript-app-template/blob/764d91f0cdfab0dcd4d2af5d5e9b04d6bcad5053/src/__tests__/getWelcomeMessage.spec.ts#L16

import assert from "node:assert";
import {describe, it} from "node:test";
import {getWelcomeMessage} from "../getWelcomeMessage";
import * as getWelcomeMessageLib from "../getWelcomeMessage";

void describe('getWelcomeMessage', () => {
  void describe("GIVEN mocked welcome message", () => {
    void it("SHOULD return mocked welcome message", (t) => {
      const expected = "Hello, World!";

      const fn = t.mock.method(getWelcomeMessageLib, "getWelcomeMessage");
      fn.mock.mockImplementation(() => expected);

      const actual = getWelcomeMessage();
      assert.strictEqual(actual, expected)
    })
  })
});

Operating system

Mac OS Ventura 13.6.1

Scope

test runner

Module and version

package.json:

{
  "name": "learn-node-esm",
  "type": "module",
  "scripts": {
    "start": "node --no-warnings=ExperimentalWarning --loader @swc-node/register/esm src/main.ts",
    "dev": "node --no-warnings=ExperimentalWarning --loader @swc-node/register/esm --watch src/main.ts",
    "test": "node --no-warnings=ExperimentalWarning --loader @swc-node/register/esm --test **/*.spec.ts",
    "lint": "eslint --ext .ts src/"
  },
  "main": "src/main.ts",
  "engines": {
    "node": "^20.9.0",
    "yarn": "4.0.1"
  },
  "packageManager": "yarn@4.0.1",
  "devDependencies": {
    "@swc-node/register": "^1.6.8",
    "@swc/core": "^1.3.96",
    "@tsconfig/node20": "^20.1.2",
    "@tsconfig/strictest": "^2.0.2",
    "@types/eslint": "^8.44.7",
    "@types/node": "^20.9.0",
    "@typescript-eslint/eslint-plugin": "^6.11.0",
    "@typescript-eslint/parser": "^6.11.0",
    "eslint": "^8.53.0",
    "typescript": "^5.2.2"
  }
}

tsconfig.json:

{
  "$schema": "https://json.schemastore.org/tsconfig",
  "extends": [
    "@tsconfig/node20/tsconfig.json",
    "@tsconfig/strictest/tsconfig.json",
  ],
  "compilerOptions": {
    "module": "ESNext",
    "moduleResolution": "bundler",
  }
}
BrummbaerFr commented 7 months ago

I am wondering the same thing.

From what I could see online, people usually show how to mock a function that exists within the test file, such as:

const sum = mock.fn((a, b) => {
    return a + b;
  });

But I could not find an example of how to mock an exported function, as mentioned by @tlan16, and thus am wondering if it is even possible.

tlan16 commented 7 months ago

I think it's fine mocking named export is not something node test runner aids to support. If so, will be nice make it clear in the doc.

mdedys commented 5 months ago

Something like this works:

const A = { MyFunc: () => {} }
export default A
import A from "./A.js"
mock.method(A, "myFunc", () => Promise.resolve());

The caveat being the default export is mockable. I have not found a way to mock individual export.

RedYetiDev commented 5 days ago

Is this issue still occuring? If not, feel free to self-close.