Mocha является одним из самых популярных фреймворков для тестирования в JavaScript. Однако одной из основных проблем при написании тестов является необходимость имитировать поведение внешних зависимостей, таких как API, базы данных или сторонние сервисы. Это особенно важно при тестировании модулей, которые не могут работать без этих зависимостей. Для решения этой проблемы используются стаб (stub) — объекты или функции, которые заменяют настоящие реализации.
Стаб — это искусственная замена функции или метода, предназначенная для того, чтобы контролировать поведение кода, с которым работает тестируемая единица. Стаб может быть использован для того, чтобы:
В Mocha стабирование обычно осуществляется с использованием
библиотеки sinon, которая предоставляет удобные методы для
создания стабов, шпионов и моков.
Для того чтобы использовать стабирование в Mocha, необходимо
подключить библиотеку sinon. Она предоставляет удобные
инструменты для создания стабов, а также для того, чтобы отслеживать
вызовы функций. Базовое использование выглядит следующим образом:
const sinon = require('sinon');
const assert = require('assert');
describe('Тестирование функции с использованием стабов', function() {
it('должен вернуть значение из стеба', function() {
const fakeFunction = sinon.stub().returns(42);
assert.strictEqual(fakeFunction(), 42);
});
});
В этом примере создаётся стаб с помощью sinon.stub(),
который всегда возвращает значение 42, независимо от того, что в него
передано.
Иногда необходимо создать стаб для метода, который является частью
объекта. В этом случае можно использовать sinon.stub() для
конкретного метода объекта. Пример:
const sinon = require('sinon');
const assert = require('assert');
describe('Тестирование объекта с методом', function() {
it('должен замещать метод объекта', function() {
const myObject = {
method: function() {
return 'Original value';
}
};
sinon.stub(myObject, 'method').returns('Stubbed value');
assert.strictEqual(myObject.method(), 'Stubbed value');
});
});
В данном случае метод method объекта
myObject будет заменён на стаб, который всегда возвращает
‘Stubbed value’.
Стаб также может быть настроен на возврат разных значений в
зависимости от переданных аргументов. Для этого можно использовать
функцию withArgs(), которая позволяет задать поведение
стабов в зависимости от входных параметров:
const sinon = require('sinon');
const assert = require('assert');
describe('Тестирование стабов с аргументами', function() {
it('должен возвращать разные значения для разных аргументов', function() {
const fakeFunction = sinon.stub();
fakeFunction.withArgs(1).returns('Первый аргумент');
fakeFunction.withArgs(2).returns('Второй аргумент');
assert.strictEqual(fakeFunction(1), 'Первый аргумент');
assert.strictEqual(fakeFunction(2), 'Второй аргумент');
});
});
Здесь, в зависимости от переданного аргумента, стаб будет возвращать разные значения.
При тестировании асинхронных функций важно, чтобы стаб правильно
моделировал поведение промисов. В Mocha с использованием
sinon можно стабировать асинхронные методы, создавая
промисы, которые имитируют асинхронное поведение.
Пример стабирования асинхронной функции:
const sinon = require('sinon');
const assert = require('assert');
describe('Тестирование асинхронной функции с стабом', function() {
it('должен возвращать промис с правильным значением', async function() {
const fakeAsyncFunction = sinon.stub().resolves('Async result');
const result = await fakeAsyncFunction();
assert.strictEqual(result, 'Async result');
});
});
Здесь resolves() используется для того, чтобы стаб
возвращал промис, который сразу же разрешается с переданным
значением.
Иногда необходимо не только подменить поведение функции, но и отслеживать, была ли она вызвана, сколько раз и с какими аргументами. Для этого используются шпионы, но стаб также может отслеживать эти данные. Mocha и Sinon предоставляют методы для проверки вызовов:
const sinon = require('sinon');
const assert = require('assert');
describe('Тестирование вызова стабов', function() {
it('должен отслеживать количество вызовов и аргументы', function() {
const fakeFunction = sinon.stub();
fakeFunction(1, 2);
fakeFunction(3, 4);
assert.strictEqual(fakeFunction.callCount, 2);
assert.strictEqual(fakeFunction.getCall(0).args[0], 1);
assert.strictEqual(fakeFunction.getCall(1).args[1], 4);
});
});
Метод callCount позволяет узнать, сколько раз была
вызвана функция, а getCall() предоставляет доступ к данным
о конкретных вызовах.
В некоторых случаях требуется, чтобы стаб не просто возвращал данные,
но и вызывал ошибку или изменял поток исполнения. В Mocha можно
использовать метод throws(), чтобы стаб вызывал исключение
при вызове.
Пример:
const sinon = require('sinon');
const assert = require('assert');
describe('Тестирование исключений через стаб', function() {
it('должен выбрасывать ошибку при вызове', function() {
const fakeFunction = sinon.stub().throws(new Error('Ошибка!'));
assert.throws(() => {
fakeFunction();
}, /Ошибка!/);
});
});
Здесь стаб будет выбрасывать ошибку с заданным сообщением при каждом вызове.
После использования стабов в тестах важно очищать их, чтобы избежать
побочных эффектов между тестами. Для этого можно использовать метод
restore(), который восстанавливает исходное поведение
объекта или функции.
const sinon = require('sinon');
const assert = require('assert');
describe('Тестирование с очисткой стабов', function() {
let fakeFunction;
beforeEach(function() {
fakeFunction = sinon.stub().returns(42);
});
afterEach(function() {
fakeFunction.restore();
});
it('должен использовать стаб', function() {
assert.strictEqual(fakeFunction(), 42);
});
it('должен восстанавливать оригинальное поведение', function() {
assert.strictEqual(fakeFunction(), 42); // Восстановленный стаб
});
});
Метод restore() гарантирует, что после каждого теста
функции вернутся к своему исходному состоянию.
Создание стабов в Mocha с использованием библиотеки
sinon предоставляет мощные инструменты для замены
зависимостей и контроля поведения тестируемого кода. Стабирование
помогает изолировать тесты, фокусируясь только на тестируемых функциях,
без влияния внешних факторов. Важно помнить об очистке стабов после
выполнения тестов, чтобы не нарушать результаты других тестов.