8
2

More than 1 year has passed since last update.

お題は不問!Qiita Engineer Festa 2023で記事投稿!

Node.js Test Runnerでモジュールのモックをしたい

Last updated at Posted at 2023-07-12

はじめに

プライベートで書いているスクリプトのテストをしたいが、メンテナンスするパッケージを増やしたくないと思い、
Node.js v18 から標準で使えるようになったNode.js Test Runner を使ってテストできないかを調べていました。

調べてみたところ、モジュールのモックをする方法で少し詰まったので、その解決方法を書きます。
なお、今回試すのは CJS です。

やりたいテスト

今回やりたかったテストは、テスト対象のモジュール内で使用されている別のモジュールをモックするようなテストです。

例として、以下のスクリプトを使います。

add.js
exports.add = (a, b) => {
  return a + b;
};
mul.js
const { add } = require("./add");

exports.mul = (a, b) => {
  let result = 0;
  for (let i = 0; i < b; i++) {
    result = add(result, a);
  }
  return result;
};

そして、今回テストしたいのはmul関数で、add関数をモックしたいとします。

この場合であれば、mock.method 関数を使い、以下のようにモックすることができます。

mul.test.js
const { test, mock } = require("node:test");
const assert = require("node:assert");

// `mul`よりも先に`add`をモックする必要がある
const addModule = require("./add");
mock.method(addModule, "add", (a, b) => {
  return 1;
});

const { mul } = require("./mul");

test("mul", () => {
  assert.equal(mul(2, 3), 1);
});

同様にビルトインモジュールなどもモックできます。

readFileSync.test.js
const { test, mock } = require("node:test");
const assert = require("node:assert");
const fs = require("node:fs");

mock.method(fs, "readFileSync", (path) => {
  return "hoge";
});

test("readFileSync", () => {
  assert.equal(fs.readFileSync("sample.txt"), "hoge");
});

なお、モックしたいモジュールがmodule.exportsで定義されている場合、mock.methodではモックできないようです。(いろいろ試したけど、できる方法を見つけれなかった。Module._loadでモック関数を返すしか思いつかなかった。)

Refs

8
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
2