mocha の使い方

simple, flexible, fun test framework

v11.7.5/週MITテスト
AI生成コンテンツ

この記事はAIによって生成されました。内容の正確性は保証されません。最新の情報は公式ドキュメントをご確認ください。

mocha の使い方 — JavaScriptの柔軟なテストフレームワーク

一言でいうと

mocha は、Node.js およびブラウザ環境で動作する、シンプルかつ柔軟なJavaScript/TypeScriptテストフレームワークです。BDD・TDD・QUnitなど複数のテストスタイルをサポートし、アサーションライブラリやレポーターを自由に組み合わせて使えます。


どんな時に使う?

  • Node.jsアプリケーションのユニットテスト・統合テストを書きたい時 — Express/Fastifyなどのバックエンドロジックのテストに最適です
  • アサーションライブラリやモックライブラリを自分で選びたい時 — Jestのようなオールインワンではなく、chai・sinon・nockなどを自由に組み合わせたい場合に向いています
  • 既存プロジェクトのテスト基盤がmochaで構築されている時 — 長い歴史を持つフレームワークのため、レガシー〜中規模プロジェクトで広く採用されています

インストール

# npm
npm install --save-dev mocha

# yarn
yarn add --dev mocha

# pnpm
pnpm add --save-dev mocha

TypeScriptで使う場合は型定義も追加します。

npm install --save-dev @types/mocha

基本的な使い方

ディレクトリ構成

project/
├── src/
│   └── math.ts
├── test/
│   └── math.test.ts
├── package.json
└── .mocharc.yml

テスト対象のコード

// src/math.ts
export function add(a: number, b: number): number {
  return a + b;
}

export function divide(a: number, b: number): number {
  if (b === 0) {
    throw new Error("Division by zero");
  }
  return a / b;
}

テストコード

mocha はアサーションライブラリを同梱していないため、Node.js 組み込みの assertchai などを別途使います。ここでは Node.js 標準の assert を使用します。

// test/math.test.ts
import assert from "node:assert/strict";
import { add, divide } from "../src/math.js";

describe("add", () => {
  it("2つの正の数を加算できる", () => {
    assert.equal(add(1, 2), 3);
  });

  it("負の数を加算できる", () => {
    assert.equal(add(-1, -2), -3);
  });
});

describe("divide", () => {
  it("正常に除算できる", () => {
    assert.equal(divide(10, 2), 5);
  });

  it("ゼロ除算でエラーをスローする", () => {
    assert.throws(() => divide(10, 0), {
      message: "Division by zero",
    });
  });
});

設定ファイル

# .mocharc.yml
require:
  - tsx
spec: "test/**/*.test.ts"
timeout: 5000

補足: TypeScriptを直接実行するために tsxts-node などのローダーが必要です。npm install --save-dev tsx でインストールしてください。

実行

// package.json
{
  "scripts": {
    "test": "mocha"
  }
}
npm test

出力例:

  add
    ✓ 2つの正の数を加算できる
    ✓ 負の数を加算できる

  divide
    ✓ 正常に除算できる
    ✓ ゼロ除算でエラーをスローする

  4 passing (12ms)

よく使うAPI

1. describe / it — テストスイートとテストケースの定義

最も基本的なBDDスタイルのインターフェースです。

describe("User", () => {
  describe("#save()", () => {
    it("データベースにユーザーを保存できる", async () => {
      const user = new User({ name: "Alice" });
      const result = await user.save();
      assert.equal(result.name, "Alice");
    });
  });
});

2. before / after / beforeEach / afterEach — フック(セットアップ・ティアダウン)

テストの前後に実行する処理を定義します。

import assert from "node:assert/strict";

describe("Database操作", () => {
  let db: Database;

  before(async () => {
    // テストスイート全体の前に1回だけ実行
    db = await Database.connect("test_db");
  });

  after(async () => {
    // テストスイート全体の後に1回だけ実行
    await db.disconnect();
  });

  beforeEach(async () => {
    // 各テストケースの前に毎回実行
    await db.clear();
  });

  afterEach(() => {
    // 各テストケースの後に毎回実行
    console.log("テストケース完了");
  });

  it("レコードを挿入できる", async () => {
    await db.insert({ id: 1, name: "Alice" });
    const count = await db.count();
    assert.equal(count, 1);
  });
});

3. .only / .skip — テストの絞り込みとスキップ

デバッグ時に特定のテストだけ実行したり、一時的にスキップしたりできます。

describe("Feature A", () => {
  // このテストだけ実行される
  it.only("重要なテスト", () => {
    assert.equal(1 + 1, 2);
  });

  // スキップされる(.onlyがある場合もスキップ)
  it("別のテスト", () => {
    assert.equal(2 + 2, 4);
  });
});

describe("Feature B", () => {
  // 明示的にスキップ(pending扱い)
  it.skip("未実装のテスト", () => {
    // TODO: 後で実装
  });
});

注意: .only をコミットに含めないよう注意してください。CIで全テストが実行されなくなります。--forbid-only フラグをCI環境で使うと安全です。

4. this.timeout() / this.retries() — タイムアウトとリトライ

テストごとにタイムアウトやリトライ回数を制御できます。

describe("外部API連携", function () {
  // スイート全体のタイムアウトを設定
  this.timeout(10000);

  // 不安定なテストのリトライ回数を設定
  this.retries(3);

  it("APIからデータを取得できる", async function () {
    // 個別のテストでタイムアウトを上書き
    this.timeout(15000);

    const response = await fetch("https://api.example.com/data");
    assert.equal(response.status, 200);
  });
});

注意: アロー関数 () => {} では this が束縛されないため、this.timeout() などを使う場合は function() {} を使ってください。

5. 非同期テスト — Promise / async-await / コールバック

mocha は複数の非同期パターンをサポートしています。

// async/await(推奨)
it("async/awaitでテストできる", async () => {
  const data = await fetchData();
  assert.deepEqual(data, { id: 1, name: "Alice" });
});

// Promiseを返す
it("Promiseを返してテストできる", () => {
  return fetchData().then((data) => {
    assert.deepEqual(data, { id: 1, name: "Alice" });
  });
});

// コールバック(done)
it("コールバックでテストできる", (done) => {
  fetchDataWithCallback((err, data) => {
    if (err) return done(err);
    try {
      assert.deepEqual(data, { id: 1, name: "Alice" });
      done();
    } catch (e) {
      done(e);
    }
  });
});

類似パッケージとの比較

特徴mochaJestVitest
アサーション外部ライブラリ(chai等)組み込み(expect)組み込み(expect互換)
モック外部ライブラリ(sinon等)組み込み(jest.fn)組み込み(vi.fn)
スナップショットテストプラグインで対応組み込み組み込み
コードカバレッジ外部(nyc / c8)組み込み(--coverage)組み込み(c8 / v8)
ESM対応○(設定が必要な場合あり)◎(ネイティブ)
設定の自由度◎(高い)○(中程度)○(中程度)
実行速度◎(Vite活用)
学習コストやや高い(組み合わせが必要)低い(オールインワン)低い(Jest互換API)
ブラウザテスト○(ネイティブ対応)jsdom○(ブラウザモード)

選定の目安:

  • 新規プロジェクト → Vitest(Vite利用時)または Jest が第一候補
  • アサーション・モックを自分で選びたい → mocha
  • 既存のmochaプロジェクトの保守 → そのまま mocha を継続

注意点・Tips

1. アロー関数と this の問題

mocha のコンテキスト(this.timeout() など)を使う場合、アロー関数は使えません。

// ❌ NG: アロー関数ではthisが使えない
describe("example", () => {
  it("test", () => {
    this.timeout(5000); // TypeError
  });
});

// ✅ OK: function式を使う
describe("example", function () {
  it("test", function () {
    this.timeout(5000);
  });
});

this を使わないテストであればアロー関数で問題ありません。

2. CIでの --forbid-only--exit

{
  "scripts": {
    "test": "mocha",
    "test:ci": "mocha --forbid-only --exit"
  }
}
  • --forbid-only: .only が残っていたらエラーにする
  • --exit: テスト完了後にプロセスを強制終了する(DB接続やタイマーが残っている場合に有用)

3. .mocharc.yml で設定を一元管理する

# .mocharc.yml
require:
  - tsx
spec: "test/**/*.test.ts"
timeout: 5000
recursive: true
reporter: spec
forbid-only: false  # CIではtrueに

コマンドライン引数を毎回書く必要がなくなります。package.json"mocha" キーでも設定可能です。

4. chai との組み合わせ

mocha と最もよく組み合わせて使われるアサーションライブラリが chai です。

npm install --save-dev chai @types/chai
import { expect } from "chai";

describe("chai との組み合わせ", () => {
  it("expectスタイルでアサーションできる", () => {
    expect([1, 2, 3]).to.have.lengthOf(3);
    expect({ name: "Alice" }).to.deep.equal({ name: "Alice" });
    expect(() => { throw new Error("fail"); }).to.throw("fail");
  });
});

5. レポーターの変更

# ドット表示(CI向け)
mocha --reporter dot

# 最小表示
mocha --reporter min

# JSON出力
mocha --reporter json

# nyan cat(お楽しみ)
mocha --reporter nyan

まとめ

mocha は「テストランナーに徹し、それ以外は自分で選ぶ」という Unix 哲学的な設計のテストフレームワークです。アサーション・モック・カバレッジツールを自由に組み合わせられる柔軟性が最大の強みですが、その分セットアップにはやや手間がかかります。新規プロジェクトでは Jest や Vitest も有力な選択肢ですが、既存の mocha ベースのプロジェクトでは引き続き安定して活用できるフレームワークです。