TL;DR
- Mocha предоставляет структуру тестов (
describe,it) — приноси свою assertion library- Сочетай с Chai для читаемых assertions:
expect(value).to.equal(expected)- Hooks:
before,after,beforeEach,afterEachдля setup/teardown- Async поддержка: callbacks (
done), promises, async/await — всё работает- Гибкий и модульный — выбирай свои инструменты
Идеально для: Node.js проектов, команд, желающих выбор assertion library Пропусти, если: Предпочитаешь всё-в-одном решения (используй Jest) Время чтения: 14 минут
Твоему Node.js проекту нужны тесты. Jest кажется тяжёлым для маленького сервиса. Ты хочешь выбрать свой стиль assertions. Тебе нужно что-то, что работает с существующими инструментами.
Mocha не мешает. Он запускает тесты, предоставляет hooks, обрабатывает async — не более. Ты выбираешь assertion library, инструмент мокирования и reporter.
Что такое Mocha?
Mocha — JavaScript тест-фреймворк для Node.js и браузеров. Предоставляет структуру для организации тестов, но намеренно оставляет assertions и mocking другим библиотекам.
Почему Mocha:
- Гибкий — работает с любой assertion library
- Async-friendly — callbacks, promises, async/await
- Богатая экосистема — много reporters и плагинов
- Browser support — те же тесты работают в Node и браузере
Установка и настройка
npm install mocha chai --save-dev
// package.json
{
"scripts": {
"test": "mocha",
"test:watch": "mocha --watch"
}
}
// .mocharc.json
{
"spec": "test/**/*.test.js",
"timeout": 5000,
"recursive": true
}
Написание первого теста
// test/calculator.test.js
const { expect } = require('chai');
const Calculator = require('../src/calculator');
describe('Calculator', () => {
describe('add()', () => {
it('должен сложить два положительных числа', () => {
const calc = new Calculator();
expect(calc.add(2, 3)).to.equal(5);
});
it('должен обработать отрицательные числа', () => {
const calc = new Calculator();
expect(calc.add(-1, 1)).to.equal(0);
});
});
});
Chai Assertions
const { expect } = require('chai');
// Равенство
expect(value).to.equal(5);
expect(value).to.deep.equal({ a: 1 });
// Проверка типов
expect('hello').to.be.a('string');
expect([1, 2]).to.be.an('array');
// Сравнения
expect(10).to.be.above(5);
expect(10).to.be.below(20);
// Строки
expect('hello world').to.include('world');
expect('hello').to.have.lengthOf(5);
// Массивы
expect([1, 2, 3]).to.include(2);
expect([1, 2, 3]).to.have.lengthOf(3);
// Объекты
expect({ a: 1 }).to.have.property('a');
// Ошибки
expect(() => fn()).to.throw();
expect(() => fn()).to.throw('error message');
Lifecycle Hooks
describe('User Service', () => {
let db;
before(async () => {
// Один раз перед всеми тестами
db = await connectToDatabase();
});
after(async () => {
// Один раз после всех тестов
await db.close();
});
beforeEach(() => {
// Перед каждым тестом
});
afterEach(async () => {
// После каждого теста
await db.collection('users').deleteMany({});
});
it('должен создать пользователя', async () => {
// ...
});
});
Async тестирование
Async/Await (Рекомендуется)
it('должен получить пользователя', async () => {
const user = await fetchUser(1);
expect(user.name).to.equal('John');
});
it('должен обработать ошибки', async () => {
try {
await fetchUser(999);
expect.fail('Должен был выбросить ошибку');
} catch (err) {
expect(err.message).to.include('not found');
}
});
Timeout
it('должен завершиться за 5 секунд', async function() {
this.timeout(5000);
await longRunningOperation();
});
Mocking с Sinon
npm install sinon --save-dev
const sinon = require('sinon');
const axios = require('axios');
describe('API Client', () => {
let axiosStub;
beforeEach(() => {
axiosStub = sinon.stub(axios, 'get');
});
afterEach(() => {
axiosStub.restore();
});
it('должен получить данные', async () => {
axiosStub.resolves({ data: { id: 1, name: 'Test' } });
const result = await apiClient.fetchUser(1);
expect(result.name).to.equal('Test');
});
});
CI/CD интеграция
# .github/workflows/test.yml
name: Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- run: npm test
Mocha с помощью ИИ
Что ИИ делает хорошо:
- Генерировать тест-кейсы из сигнатур функций
- Создавать вариации assertions для edge cases
- Конвертировать между стилями assertions
- Предлагать mock-реализации
Что требует людей:
- Решать что тестировать
- Понимать бизнес-логику
- Отлаживать flaky тесты
FAQ
Что такое Mocha?
Mocha — гибкий JavaScript тест-фреймворк для Node.js и браузеров. Предоставляет структуру тестов (describe, it), lifecycle hooks (before, after) и async поддержку, но намеренно не включает assertions или mocking. Ты сочетаешь его с Chai для assertions и Sinon для mocking.
Mocha vs Jest — что лучше?
Jest — всё-в-одном со встроенными assertions, mocking и coverage. Mocha модулярный — ты выбираешь каждый компонент. Jest проще для старта; Mocha предлагает больше гибкости. Используй Jest для React проектов, Mocha когда нужны специфичные стили assertions.
Какая assertion library работает с Mocha?
Chai — самый популярный выбор с тремя стилями: expect (BDD), should (BDD) и assert (TDD). Встроенный Node assert тоже работает. Большинство команд предпочитают Chai expect стиль за читаемость.
Может ли Mocha тестировать async код?
Да, отлично. Mocha поддерживает три async паттерна: callbacks (параметр done), promises (вернуть promise) и async/await (просто использовать async функцию). Mocha обрабатывает все паттерны нативно.
Официальные ресурсы
Смотрите также
- Jest Testing Tutorial - Всё-в-одном альтернатива
- Cypress Tutorial - E2E тестирование
- WebdriverIO Tutorial - Автоматизация браузера с Mocha
- GitHub Actions для QA - CI/CD интеграция
