Sinon: Spies, Stubs, Mocks
Sinon — mock-библиотека для JavaScript, которая помогает в написании unit тестов. Она позволяет создавать Fakes, которые необходимы для тестирования.
В unit тесте вам может потребоваться не проверять некоторые зависимости и функции. Например, нам не нужно записывать в базу данные, когда мы что-то тестируем. Также может возникнуть необходимость не запускать некоторые стандартные модули. В этом случае нам помогут Fakes, которые мы создаем с помощью Sinon. Предлагается несколько видов, в частности spies, stubs и mocks. Между ними есть некоторые существенные различия в работе и использовании, рассмотрим их в деталях.
Sinon Spies
Spies — это функции, которые принимают аргументы и возвращают значение или ошибку, если она была. Spy это может быть анонимная функция или созданная по верху существующей. Используется когда поведение функции шпионажа не тестируется.
Рассмотрим варианты создания Spy:
- Создать анонимную функцию, которая записывает аргументы текущего значения, сообщения про ошибки и аргументы возвращенного значения для всех вызовов.
let spy = sinon.spy();
- Создает шпиона поверх готовой функции.
let spy = sinon.spy(myFunc);
- Создает шпиона для object.method и заменяет исходный метод.
let spy = sinon.spy(object, "method"); // Для востановления первоначального метода object.method.restore ().
Пример 1: использование Spy.
describe("#fight", function () {
it("calls prayForStrength for fight success", function () {
sinon.spy(subject.strengthDep, "prayForStrength");
subject.fight();
subject.strengthDep.called.should.be.true;
subject.strengthDep.restore();
});
});
Spies не изменяют функциональность вашего приложения. Сначала мы настраиваем Spy для функции или метода, после вызываем функцию, для которой создали Spy, а после верифицируем было ли вызвано то, что мы хотели.
Sinon Stubs
Stubs — это функции с предварительно запрограммированным поведением. Они не вызывают существующую функцию, а тестируют была ли она вызвана. Как и Spies, Stubs могут быть анонимными или обертывать существующие функции.
Stubs можно использовать, например, если у вас была функция, которая возвращала логическое значение в коде. Вы можете использовать заглушку в двух разных тестах, чтобы проверить условия при возврате разных значений (т.е вы можете сделать return true или return false и при этом не вызывать функцию).
Рассмотрим варианты создания Stubs:
- Создать анонимную функцию
let stub = sinon.stub();
- Создает Stubs для метода.
let stub = sinon.stub(object, "method"); // Исходная функция может быть восстановлена, вызвав object.method.restore (); // или stub.restore ();
- Создает Stubs для метода и при этом подменяет метод для тестирования
let stub = sinon.stub(object, "method", func); // Для востановления первоначального метода object.method.restore ().
Пример 2: использование Stubs.
describe("#fight", function () {
it("always wins when prayForStrength is true", function () {
sinon.stub(subject.strengthDep, "prayForStrength", function () { return true; });
subject.fight().should.be.true;
subject.strengthDep.restore();
});
});
Здесь мы заменили метод strengthDep для subject и тестируем fight(). Мы не вызываем оригинальную subject.strengthDep, мы просто ее подменили своей функцией, которая возвращает true.
Sinon Mocks
Mocks являются имитационным методами (как Spies) с предварительно запрограммированным поведением (как Stubs), а также предварительно запрограммированным ожиданием. Mocks будет наблюдать за вызовом функции и проверять, что её вызывали определенным образом.
Рассмотрим варианты создания Mocks:
- Создает имитацию для указанного объекта. Сам объект не изменяется, но обертывает mock-обект для установки ожиданий на методах объекта.
let mock = sinon.mock(obj);
- Переопределяет obj.method с функцией имитации и возвращает его
let expectation = mock.expects("method");
restore — восстанавливает все методы имитации.
mock.restore();
verify — приводит поиск указанной имитации. Если указанная имитация не была обнаружена, выдается сообщение про ошибку.
mock.verify();
Пример 3: использование Mocks.
describe("#fight", function () {
it("always wins when prayForStrength is true", function () {
var mock = sinon.mock(subject.strengthDep)
mock.expects("prayForStrength").returns(true);
subject.fight().should.be.true;
mock.verify();
mock.restore();
});
});
Мы создали mock для метода subject.strengthDep, после записываем ожидание mock.expects в которое помещаем нашу замоканую функцию и в returns указываем значение которое вернется. Дальше проверяем что вернет наша функция subject.fight() и тестируем была ли вызвана замоканая функция.
Мы рассмотрели зачем используются Fakes при написании тестов и какие бывают их виды, а так же основные отличия и сферы использования.