chai、enzyme、jest、mocha、react-testing-library は、JavaScriptおよびReactアプリケーションのテストを支援するnpmパッケージです。mocha と jest はテストランナーとしてテストの実行環境を提供し、chai は期待値の検証(アサーション)を行うライブラリです。一方、enzyme と react-testing-library はReactコンポーネントのレンダリングや操作を簡潔に行うためのユーティリティであり、特にユーザーインタラクションに基づくテストを可能にします。これらのツールは単独で使うこともありますが、多くの場合、mocha + chai のように組み合わせて利用されます。
フロントエンド開発において、信頼性の高いテストは欠かせません。しかし「どのテストライブラリを使うべきか?」という問いには、単純な答えはありません。各パッケージは異なる役割を果たし、組み合わせて使うことも多いです。ここでは、chai、enzyme、jest、mocha、react-testing-library の5つを、実際の開発現場での使い方を中心に深く比較します。
まず、これらのパッケージは同じカテゴリに属していません。混同しがちですが、役割は大きく異なります。
mocha と jest は テストランナー(テストフレームワーク) です。テストの実行、レポート、ライフサイクル管理を担います。chai は アサーションライブラリ で、期待値と実際の値を比較するための文法を提供します。enzyme と react-testing-library は Reactコンポーネントのテスト用ユーティリティ で、DOMのレンダリングや操作をサポートします。つまり、mocha + chai のように組み合わせて使うのが一般的です。一方、jest はアサーション機能を内蔵しているため、単体で完結できます。
mocha はテスト構造(describe / it)を提供し、アサーションは別途必要です。多くの場合、chai と組み合わせて使われます。
// mocha + chai
const { expect } = require('chai');
const add = (a, b) => a + b;
describe('add関数', () => {
it('2つの数値を足す', () => {
expect(add(2, 3)).to.equal(5);
});
});
chai は expect、should、assert の3つのインターフェースを持ち、好みに応じて選べます。柔軟性が高い反面、設定が増えるのがデメリットです。
jest はテストランナー、アサーション、モック、カバレッジ計測をすべて内蔵しています。
// jest
const add = (a, b) => a + b;
test('2つの数値を足す', () => {
expect(add(2, 3)).toBe(5);
});
設定不要で即座にテストを始められ、特にReactプロジェクトではViteやCreate React Appとの統合もスムーズです。
enzyme はAirbnbが開発したReactテストユーティリティで、コンポーネントの内部状態やpropsに直接アクセスできます。
// enzyme
import { shallow } from 'enzyme';
import MyComponent from './MyComponent';
test('stateが初期化されていること', () => {
const wrapper = shallow(<MyComponent />);
expect(wrapper.state('count')).toBe(0);
});
ただし、公式ドキュメントによると、EnzymeはReact 18以降を正式にサポートしておらず、新規プロジェクトでの使用は推奨されていません。GitHubリポジトリにも「メンテナンスモード」である旨が記載されています。
react-testing-library(RTL)は、ユーザが実際にどう操作するかを重視したテストを促します。内部状態ではなく、DOMの出力やイベントを通じて検証します。
// react-testing-library
import { render, screen, fireEvent } from '@testing-library/react';
import MyComponent from './MyComponent';
test('ボタンクリックでカウントが増える', () => {
render(<MyComponent />);
fireEvent.click(screen.getByText('Increment'));
expect(screen.getByText('Count: 1')).toBeInTheDocument();
});
このアプローチは、実装の詳細に依存せず、リファクタリングに強いテストを書けます。現在、Reactコミュニティの主流となっています。
jest はTypeScript、Babel、ES Modulesなど、現代的なフロントエンドスタックとの統合が非常にスムーズです。特にViteプロジェクトでも @vitest/jest や vite-jest を使えば簡単に導入できます。
// jest.config.js(多くの場合不要)
module.exports = {
testEnvironment: 'jsdom',
};
mocha と chai を使う場合、以下の設定が必要になることが多いです:
// .mocharc.json
{
"require": ["@babel/register", "jsdom-global/register"],
"reporter": "spec"
}
小規模プロジェクトや特殊な要件がある場合を除き、設定コストは見逃せません。
jest は関数のモック、モジュールのモック、タイマーの操作などを標準でサポートしています。
// jest mock
test('APIが呼ばれる', () => {
const mockFetch = jest.fn();
mockFetch.mockResolvedValue({ data: 'ok' });
// ...テスト実行
expect(mockFetch).toHaveBeenCalled();
});
mocha 自体にはモック機能がありません。通常、sinon を組み合わせます。
// mocha + sinon + chai
const sinon = require('sinon');
const { expect } = require('chai');
test('APIが呼ばれる', () => {
const stub = sinon.stub().resolves({ data: 'ok' });
// ...テスト実行
expect(stub.calledOnce).to.be.true;
});
依存が増え、学習コストも上がります。
| プロジェクトタイプ | 推奨スタック |
|---|---|
| 新規Reactアプリ | jest + react-testing-library |
| レガシーReact(<16.8) | mocha + chai + enzyme(移行を検討) |
| 非Reactフロントエンド | jest 単体 or mocha + chai |
| 軽量テスト(Node.jsのみ) | mocha + chai(DOM不要な場合) |
重要な注意点:EnzymeはReact 18の新しいレンダリングモデル(Concurrent Renderingなど)に対応しておらず、公式GitHubリポジトリには「このプロジェクトはメンテナンスモードに入っており、新機能は追加されない」と明記されています。新規プロジェクトでは、代わりに react-testing-library を使うことを強く推奨します。
jest + react-testing-library を選ぶべきです。設定が少なく、コミュニティサポートも充実しています。テストはコードの品質を守る盾です。その盾自体が壊れていては意味がありません。信頼性と将来性を重視したツール選びが、チームの生産性を左右します。
jestは設定不要でテストをすぐに始めたい場合、またはReact/Vueなどのモダンフロントエンドフレームワークと統合したい場合に最適です。アサーション、モック、カバレッジ計測がすべて内蔵されており、TypeScriptやBabelとの連携もスムーズです。
chaiは柔軟なアサーションスタイル(expect/should/assert)を必要とする場合に選択します。特にmochaやjasmineといった他のテストランナーと組み合わせて使うのが一般的です。ただし、jestのように内蔵アサーションを持つフレームワークを使っている場合は不要です。
enzymeはReact 16以前のレガシープロジェクトで内部状態やpropsに直接アクセスするテストが必要な場合に限定して使用します。ただし、React 18以降をサポートしていないため、新規プロジェクトでは絶対に使用しないでください。代わりにreact-testing-libraryへの移行を強く推奨します。
mochaはテストランナーとして柔軟な拡張性が必要な場合や、特定のレポーター、タイムアウト制御、非同期テストの細かい制御をしたい場合に選択します。ただし、アサーションやモック機能は内蔵していないため、chaiやsinonなどとの組み合わせが必要です。
react-testing-libraryはReactコンポーネントをユーザーの視点からテストしたい場合に選択します。内部実装に依存せず、DOMの出力やイベントを通じて検証するため、リファクタリングに強いテストが書けます。現在のReactテストのデファクトスタンダードであり、新規プロジェクトではこれを使用すべきです。
🃏 Delightful JavaScript Testing
👩🏻💻 Developer Ready: Complete and ready to set-up JavaScript testing solution. Works out of the box for any React project.
🏃🏽 Instant Feedback: Failed tests run first. Fast interactive mode can switch between running all tests or only test files related to changed files.
📸 Snapshot Testing: Jest can capture snapshots of React trees or other serializable values to simplify UI testing.
Read More: https://jestjs.io/