В этой статье мы анализируем различия функций восстановления, сброса, resetHistory и resetBehaviour в sinon, а также их поведение в зависимости от того, являются ли наши подделки sinon анонимными или они обертывают существующие свойства.
Очень распространенный подход при работе с sinon, как показано в их собственной документации, - это вызов функции restore
как часть хука afterEach
Mocha.
afterEach(function () {
// completely restore all fakes created through the sandbox
sandbox.restore();
});
Этого должно быть достаточно, чтобы убедиться, что все вернется в норму, когда начнется новый тест, и они не влияют друг на друга, верно? Что ж, это иногда не так.
Давайте посмотрим на следующий пример:
Похоже, restore
отлично справился со своей задачей, за исключением счетчика вызовов log.info
шпиона. Мы ожидали, что он будет вызван только один раз в рамках второго модульного теста, но оказалось, что счетчик вызовов из предыдущего модульного теста не был должным образом сброшен, а значение callCount
шпиона равно 3.
Почему sinon.restore не работает так, как я ожидал?
Если мы посмотрим на документацию по restore
функции шпиона sinon, мы прочитаем следующее:
Заменяет шпиона исходным методом. Доступно только в том случае, если шпион заменил существующий метод.
Выделенное предложение является ключевым. Функции restore
в sinon работают только со шпионами и заглушками, которые заменяют существующий метод, а наш шпион был создан как анонимный (автономный) шпион.
Следовательно, restore
не сбрасывает счетчик вызовов, который будет продолжать увеличиваться по мере вызова шпионской функции в последующих тестах.
Как заставить его работать?
Знакомство с функциями сброса и сброса истории
Если мы посмотрим на документацию, мы обнаружим, что шпионы и заглушки имеют некоторые из следующих функций:
resetHistory
: для шпионов сбрасывает состояние; для заглушек сбрасывает вызов истории. Для песочницы сбрасывается история всех заглушек, созданных в песочнице.resetBehavior
: доступно только для заглушек и песочниц, сбрасывает исходное поведение заглушки.reset
: для заглушек сбрасывает поведение и историю; для песочницы сбрасывает внутреннее состояние всего, что создано в песочнице.
В нашем примере мы можем использовать функцию resetHistory
, чтобы убедиться, что счетчик вызовов шпиона сбрасывается после первого теста, чтобы его выполнение не противоречило второму тесту. Мы можем сделать это как часть afterEach
хука Mocha:
afterEach(() => { sandbox.restore(); log.info.resetHistory(); });
Имейте в виду: добавление sandbox.reset()
в ловушку afterEach
не поможет, но это сработает, если мы добавим его в конец первого модульного теста - до сих пор не поняли, почему это происходит.
Или просто избегайте использования анонимных шпионов
Это был бы другой вариант. Вместо использования анонимных шпионов:
const log = { info: sandbox.spy(), error: sandbox.spy() };
Создайте общий фиктивный объект журнала и установите на него шпионов:
const log = { info: function () { /* Do nothing */ }, error: function () { /* Do nothing */ } }; sandbox.spy(log, 'info'); sandbox.spy(log, 'error');