Моки (или заглушки) являются важной частью тестирования, особенно когда требуется изолировать компоненты системы от внешних зависимостей. В рамках тестирования с Mocha создание моков помогает смоделировать поведение различных частей системы, обеспечивая таким образом стабильность тестов, даже если некоторые части не готовы или трудно тестируемы. В этой главе подробно рассматривается, как создавать моки для тестов в Mocha, используя различные инструменты.
Мок – это объект, который имитирует поведение настоящего объекта, но с заранее заданной логикой. Это позволяет тестировать компоненты системы, не взаимодействуя с реальными внешними зависимостями, такими как базы данных, API или другие сервисы. Моки обычно используются для:
В Mocha часто используется библиотека Sinon для создания моков, шпионов и стабов. Она предоставляет удобные инструменты для создания мок-объектов, которые можно настраивать для тестирования взаимодействий.
Для использования Sinon в Mocha необходимо установить его через npm:
npm install sinon --save-dev
Sinon предоставляет несколько типов объектов для тестирования:
Чтобы создать мок в Sinon, используется метод
sinon.mock. Моки могут быть привязаны к объектам, и их
можно настраивать для проверки того, как часто и с какими параметрами
был вызван метод.
Пример создания мока:
const sinon = require('sinon');
describe('Тестирование моков', function() {
it('должен вызывать метод 1 раз', function() {
const obj = {
method: function() {}
};
const mock = sinon.mock(obj);
mock.expects('method').once();
obj.method();
mock.verify();
});
});
В этом примере создается объект с методом method, и мы
ожидаем, что он будет вызван ровно один раз. После вызова метода
проверяется, был ли он вызван, с помощью метода verify.
Моки также могут быть настроены для подмены возвращаемых значений.
Для этого можно использовать метод withArgs и
returns:
const sinon = require('sinon');
describe('Тестирование моков с подменой значений', function() {
it('должен возвращать подмененное значение', function() {
const obj = {
method: function(x) {
return x * 2;
}
};
const mock = sinon.mock(obj);
mock.expects('method').withArgs(2).returns(4);
const result = obj.method(2);
mock.verify();
result.should.equal(4);
});
});
В этом примере мы ожидаем, что метод method будет вызван
с аргументом 2 и вернет 4.
Для работы с асинхронными методами моки можно настроить с учетом задержек и промисов. Например:
const sinon = require('sinon');
describe('Тестирование асинхронных моков', function() {
it('должен работать с асинхронными методами', function(done) {
const obj = {
asyncMethod: async function() {
return 'done';
}
};
const mock = sinon.mock(obj);
mock.expects('asyncMethod').resolves('done');
obj.asyncMethod().then((result) => {
result.should.equal('done');
mock.verify();
done();
});
});
});
Здесь используется метод resolves, который подменяет
возвращаемое значение промиса, чтобы он разрешался с заранее заданным
результатом.
Хотя моки и стабы могут выполнять схожие функции, между ними есть важное различие. Моки контролируют поведение объекта и проверяют взаимодействие с ним, в то время как стабы позволяют подменить поведение функции или метода, но не проверяют взаимодействие.
Пример использования стаба:
const sinon = require('sinon');
describe('Тестирование стаба', function() {
it('должен подменить метод на заглушку', function() {
const obj = {
method: function() {
return 'original';
}
};
const stub = sinon.stub(obj, 'method').returns('stubbed');
const result = obj.method();
result.should.equal('stubbed');
stub.restore(); // Восстанавливаем оригинальный метод
});
});
Здесь метод method заменяется на стаб, который
возвращает заранее заданное значение, не проверяя, как и сколько раз он
был вызван.
В реальных приложениях часто требуется работать с несколькими зависимыми объектами. Mocha и Sinon предоставляют возможность комбинировать моки для тестирования сложных взаимодействий. Например, можно замокать несколько методов и проверить, как они взаимодействуют друг с другом.
const sinon = require('sinon');
describe('Тестирование сложных взаимодействий', function() {
it('должен проверить взаимодействие нескольких моков', function() {
const obj1 = {
fetchData: function() {
return 'data';
}
};
const obj2 = {
processData: function(data) {
return data.toUpperCase();
}
};
const mock1 = sinon.mock(obj1);
const mock2 = sinon.mock(obj2);
mock1.expects('fetchData').returns('data');
mock2.expects('processData').withArgs('data').returns('DATA');
const result = obj2.processData(obj1.fetchData());
result.should.equal('DATA');
mock1.verify();
mock2.verify();
});
});
Здесь два мока взаимодействуют друг с другом, проверяя, что метод
processData получает правильный аргумент и возвращает
нужное значение.
Создание моков в Mocha с использованием библиотеки Sinon предоставляет мощные инструменты для изоляции компонентов и проверки их взаимодействий. Моки позволяют подменять поведение объектов и проверять, как они взаимодействуют с другими частями системы. Правильное использование моков помогает писать более стабильные и изолированные тесты, что критически важно для поддержания качества кода.