Что такое Jasmine

Jasmine — это фреймворк для поведения ориентированного тестирования (Behavior Driven Development, BDD) в JavaScript. Он позволяет создавать автоматические тесты для функций, модулей и компонентов приложений без необходимости взаимодействия с браузером или DOM. Jasmine ориентирован на читаемость тестов и минимальные настройки, что делает его популярным инструментом для unit-тестирования.


Структура тестов в Jasmine

Тесты в Jasmine организуются с помощью двух основных конструкций: describe и it.

  • describe используется для группировки связанных тестов. Обычно в нём описывается функциональный блок или модуль.
  • it содержит конкретный тестовый сценарий, описывающий ожидаемое поведение функции или метода.
describe('Функция суммирования', () => {
    it('должна возвращать 5 для 2 + 3', () => {
        expect(sum(2, 3)).toBe(5);
    });
});

expect создаёт ожидание (expectation), а методы вроде toBe, toEqual, toContainматчеры, которые проверяют, соответствует ли фактический результат ожидаемому.


Основные типы матчеров

  • Сравнение значений

    • toBe(value) — проверяет строгое равенство (===).
    • toEqual(value) — проверяет равенство структуры объектов или массивов.
  • Логические проверки

    • toBeTruthy() / toBeFalsy() — проверка на истинность или ложность.
    • toBeNull() / toBeUndefined() — проверка на null или undefined.
  • Работа с массивами и строками

    • toContain(item) — проверка наличия элемента в массиве или подстроки в строке.
    • toHaveLength(number) — проверка длины массива или строки.

Подготовка и очистка тестовой среды

Jasmine предоставляет хуки для подготовки условий перед тестами и очистки после них:

  • beforeAll / afterAll — выполняются один раз перед всеми тестами и после всех тестов в блоке describe.
  • beforeEach / afterEach — выполняются перед и после каждого отдельного теста it.
describe('Тестирование массива', () => {
    let numbers;

    beforeEach(() => {
        numbers = [1, 2, 3];
    });

    afterEach(() => {
        numbers = [];
    });

    it('должен содержать число 2', () => {
        expect(numbers).toContain(2);
    });
});

Эти хуки полезны для инициализации тестовых данных, очистки состояния между тестами и предотвращения побочных эффектов.


Работа с асинхронными операциями

Jasmine поддерживает тестирование асинхронного кода через колбэки, Promises и async/await.

  • Колбэк done:
it('асинхронная операция с колбэком', (done) => {
    fetchData((data) => {
        expect(data).toBe('response');
        done();
    });
});
  • Тестирование Promise:
it('асинхронная операция с Promise', () => {
    return fetchDataPromise().then(data => {
        expect(data).toBe('response');
    });
});
  • Использование async/await:
it('асинхронная операция с async/await', async () => {
    const data = await fetchDataPromise();
    expect(data).toBe('response');
});

Асинхронные тесты особенно важны при работе с API, таймерами и любыми операциями ввода-вывода.


Шпионы, заглушки и мок-объекты

Jasmine предоставляет механизмы для шпионов (spies), которые отслеживают вызовы функций и подменяют их реализацию.

  • Создание шпиона:
const calculator = {
    add: (a, b) => a + b
};

spyOn(calculator, 'add').and.callThrough();
calculator.add(2, 3);
expect(calculator.add).toHaveBeenCalled();
expect(calculator.add).toHaveBeenCalledWith(2, 3);
  • Подмена функции на фиксированный результат:
spyOn(calculator, 'add').and.returnValue(10);
expect(calculator.add(2, 3)).toBe(10);
  • Создание фиктивной функции (mock):
const callback = jasmine.createSpy('callback');
callback();
expect(callback).toHaveBeenCalled();

Эти инструменты позволяют изолировать тестируемый код, подставляя зависимости и проверяя взаимодействия.


Настройки Jasmine и запуск тестов

Jasmine можно использовать как в браузере, так и в Node.js. В Node.js обычно используется пакет jasmine:

npm install --save-dev jasmine
npx jasmine init
npx jasmine

Тестовые файлы по умолчанию располагаются в папке spec. Каждый тестовый файл должен содержать describe и it.

Конфигурация позволяет:

  • указать пути к тестам и исходным файлам,
  • включить отчёты в формате JUnit,
  • задать таймаут для асинхронных тестов.

Организация больших тестовых наборов

Для крупных проектов важно структурировать тесты по модулям, избегать дублирования и использовать общие вспомогательные функции:

  • Разделять тесты по функциональным блокам и файлам *.spec.js.
  • Использовать beforeEach для инициализации состояния.
  • Создавать фабрики объектов и мок-данные для повторного использования.
  • Группировать похожие тесты в отдельные блоки describe, создавая иерархию.

Jasmine сочетает простоту записи тестов, мощный набор матчеров и инструментов для работы с асинхронностью и моками, что делает его удобным решением для unit-тестирования как небольших функций, так и больших приложений на JavaScript.