Шпионы
Введение
Что такое шпион для тестирования?
Шпион для тестирования — это функция, которая записывает аргументы, возвращаемое значение, значение this и сгенерированное исключение (если таковое имеется) для всех своих вызовов. Существует два типа шпионов: некоторые — анонимные функции, а другие — обертки над методами, которые уже существуют в тестируемой системе.
Создание шпиона как анонимной функции
Когда поведение функции, над которой проводится наблюдение, не тестируется, вы можете использовать шпион-анонимную функцию. Шпион ничего не сделает, кроме как запишет информацию о своих вызовах. Общим случаем использования такого шпиона является тестирование того, как функция обрабатывает обратный вызов, как в следующем упрощенном примере:
Использование шпиона для обертывания всех методов объекта
sinon.spy(object)
Обертывает все методы объекта.
Обратите внимание, что обычно лучше шпионить за отдельными методами, особенно на объектах, которые вы не понимаете или не контролируете все методы (например, зависимости библиотек).
Шпионить за отдельными методами более точно проверяет намерения и менее подвержено неожиданному поведению по мере развития кода объекта.
Следующий пример несколько искусственный:
Использование шпиона для обертывания существующего метода
sinon.spy(object, "method") создаёт шпиона, который обертывает существующую функцию object.method. Шпион будет вести себя точно так же, как и исходный метод (включая использование в качестве конструктора), но вы получите доступ к данным обо всех вызовах. Следующий пример несколько искусственный:
Использование шпиона для обертывания свойств-геттеров и -сеттеров
sinon.spy(object, "property", ["get", "set"]) создаёт шпионов, которые обертывают геттеры и сеттеры для object.property. Шпионы будут вести себя точно так же, как исходные геттеры и сеттеры, но вы получите доступ к данным обо всех вызовах. Пример:
var object = {
get test() {
return this.property;
},
set test(value) {
this.property = value * 2;
},
};
var spy = sinon.spy(object, "test", ["get", "set"]);
object.test = 42;
assert(spy.set.calledOnce);
assert.equals(object.test, 84);
assert(spy.get.calledOnce);
Создание шпионов: sinon.spy() Подписи методов
var spy = sinon.spy();- Создаёт анонимную функцию, которая записывает аргументы,
thisзначение, исключения и возвращаемые значения для всех вызовов. var spy = sinon.spy(myFunc);- Оборачивает функцию шпионом. Вы можете передать этого шпиона там, где обычно передавалась исходная функция, чтобы проверить, как используется функция.
var spy = sinon.spy(object, "method");- Создаёт шпиона для
object.methodи заменяет исходный метод шпионом. Если свойство не является функцией, выбрасывается исключение. Шпион ведет себя точно так же, как исходный метод во всех случаях. Исходный метод можно восстановить, вызвавobject.method.restore(). Возвращаемый шпион — это объект функции, заменивший исходный метод.spy === object.method. var spy = sinon.spy(object, "property", types);- Создаёт шпиона для свойства
object.property, которое заменяет дескриптор эквивалентным, где каждый указанный аксессор (параметрtypes) обернут как шпион. В отличие от обычных шпионов, возвращаемый объект — это дескриптор свойства, содержащий обернутые аксессоры (шпионы). Исходные аксессоры можно восстановить, вызвавspy.get.restore(), гдеget— это аксессор, который вы хотите восстановить.
API шпионов
Шпионы предоставляют богатый интерфейс для проверки их использования. В приведенных выше примерах показано свойство calledOnce boolean, метод getCall и свойство args возвращаемого объекта. Существует три способа проверки данных о вызовах.
Предпочтительный подход — использование метода calledWith шпиона (и его аналогов), так как это предотвращает излишнюю специфику ваших тестов относительно того, какой вызов что делал и так далее. Он вернёт true, если шпион был когда-либо вызван с предоставленными аргументами.
Если вам нужна специфичность, вы можете непосредственно проверить первый аргумент первого вызова. Существует два способа достижения этого:
В первом примере двумерный массив args используется непосредственно в шпионе, а во втором — извлекается первый объект вызова, а затем обращается к массиву args. Выбор зависит от предпочтений, но рекомендуемым подходом является использование spy.calledWith(arg1, arg2, ...), если нет необходимости в высокой специфичности тестов.
API
Объекты шпионов — это объекты, возвращаемые из sinon.spy(). При использовании шпионов для существующих методов с sinon.spy(object, method), следующие свойства и методы также доступны для object.method.
Свойства
spy.withArgs(arg1[, arg2, ...]);
Создаёт шпиона, который записывает вызовы только тогда, когда полученные аргументы совпадают с аргументами, переданными в withArgs. Это полезно для более выразительных утверждений, где вы можете получить доступ к шпиону с тем же вызовом.
Использует глубокое сравнение для объектов и массивов. Используйте spy.withArgs(sinon.match.same(obj)) для строгого сравнения (см. совпадения).
spy.callCount
Количество записанных вызовов.
spy.called
true если шпион был вызван хотя бы один раз
spy.notCalled
true если шпион не был вызван
spy.calledOnce
true если шпион был вызван ровно один раз
spy.calledTwice
true если шпион был вызван ровно два раза
spy.calledThrice
true если шпион был вызван ровно три раза
spy.firstCall
Первый вызов
spy.secondCall
Второй вызов
spy.thirdCall
Третий вызов
spy.lastCall
Последний вызов
spy.calledBefore(anotherSpy);
Возвращает true, если шпион был вызван до anotherSpy
spy.calledAfter(anotherSpy);
Возвращает true, если шпион был вызван после anotherSpy
spy.calledImmediatelyBefore(anotherSpy);
Возвращает true, если spy был вызван до anotherSpy, и никаких вызовов шпиона не произошло между spy и anotherSpy.
spy.calledImmediatelyAfter(anotherSpy);
Возвращает true, если spy был вызван после anotherSpy, и никаких вызовов шпиона не произошло между anotherSpy и spy.
spy.calledOn(obj);
Возвращает true, если шпион был вызван как минимум один раз с obj в качестве this. calledOn также принимает совпадение spyCall.calledOn(sinon.match(fn)) (см. совпадения).
spy.alwaysCalledOn(obj);
Возвращает true, если шпион всегда вызывался с obj в качестве this.
spy.calledWith(arg1, arg2, ...);
Возвращает true, если шпион был вызван как минимум один раз с указанными аргументами.
Может использоваться для частичного соответствия, Sinon проверяет только предоставленные аргументы по отношению к фактическим аргументам, поэтому вызов, который принял предоставленные аргументы (в тех же местах) и, возможно, другие тоже, вернёт true.
spy.calledOnceWith(arg1, arg2, ...);
Возвращает true, если шпион был вызван ровно один раз в целом, и этот один вызов использовал указанные аргументы.
spy.alwaysCalledWith(arg1, arg2, ...);
Возвращает true, если шпион всегда вызывался с указанными аргументами (и, возможно, другими).
spy.calledWithExactly(arg1, arg2, ...);
Возвращает true, если шпион был вызван как минимум один раз с указанными аргументами и никакими другими.
spy.calledOnceWithExactly(arg1, arg2, ...);
Возвращает true, если шпион был вызван ровно один раз в целом, и этот один вызов использовал именно указанные аргументы и никакие другие.
spy.alwaysCalledWithExactly(arg1, arg2, ...);
Возвращает true, если шпион всегда вызывался с указанными аргументами.
spy.calledWithMatch(arg1, arg2, ...);
Возвращает true, если шпион был вызван с соответствующими аргументами (и, возможно, другими).
Это работает так же, как spy.calledWith(sinon.match(arg1), sinon.match(arg2), ...).
spy.alwaysCalledWithMatch(arg1, arg2, ...);
Возвращает true, если шпион всегда вызывался с соответствующими аргументами (и, возможно, другими).
Это работает так же, как spy.alwaysCalledWith(sinon.match(arg1), sinon.match(arg2), ...).
spy.calledWithNew();
Возвращает true, если шпион/заглушка был вызван с оператором new.
Обратите внимание, что это определяется на основе значения объекта this и функции шпиона prototype, поэтому это может давать ложноположительные результаты, если вы активно возвращаете нужный тип объекта.
spy.neverCalledWith(arg1, arg2, ...);
Возвращает true, если шпион/заглушка никогда не вызывался с указанными аргументами.
spy.neverCalledWithMatch(arg1, arg2, ...);
Возвращает true, если шпион/заглушка никогда не вызывался с соответствующими аргументами.
Это работает так же, как spy.neverCalledWith(sinon.match(arg1), sinon.match(arg2), ...).
spy.threw();
Возвращает true, если шпион бросил исключение хотя бы один раз.
spy.threw("TypeError");
Возвращает true, если шпион бросил исключение указанного типа хотя бы один раз.
spy.threw(obj);
Возвращает true, если шпион бросил указанный объект исключения хотя бы один раз.
spy.alwaysThrew();
Возвращает true, если шпион всегда выбрасывал исключение.
spy.alwaysThrew("TypeError");
Возвращает true, если шпион всегда выбрасывал исключение указанного типа.
spy.alwaysThrew(obj);
Возвращает true, если шпион всегда выбрасывал предоставленный объект исключения.
spy.returned(obj);
Возвращает true, если шпион вернул предоставленное значение как минимум один раз.
Использует глубокое сравнение для объектов и массивов. Используйте spy.returned(sinon.match.same(obj)) для строгого сравнения (см. совпадения).
spy.alwaysReturned(obj);
Возвращает true, если шпион всегда возвращал предоставленное значение.
var spyCall = spy.getCall(n);
Возвращает n-й вызов.
Если n отрицательно, возвращается n-й вызов с конца. Например, spy.getCall(-1) возвращает последний вызов, а spy.getCall(-2) — предпоследний.
Доступ к отдельным вызовам помогает более детально проверить поведение, когда шпион вызывается более одного раза.
var spyCalls = spy.getCalls();
Возвращает Array всех вызовов, записанных шпионом.
spy.thisValues
Массив объектов this, spy.thisValues[0] является объектом this для первого вызова.
spy.args
Массив полученных аргументов, spy.args[0] — массив аргументов, полученных при первом вызове.
spy.exceptions
Массив объектов исключений, брошенных при spy.exceptions[0] — исключение, брошенное при первом вызове.
Если вызов не вызвал ошибку, значение в позиции вызова в .exceptions будет undefined.
spy.returnValues
Массив возвращаемых значений, spy.returnValues[0] — возвращаемое значение первого вызова.
Если вызов не явно не вернул значение, значение в позиции вызова в .returnValues будет undefined.
spy.resetHistory();
Сбрасывает состояние шпиона.
spy.restore();
Заменяет шпиона оригинальным методом. Доступно только если шпион заменил существующий метод.
spy.printf("format string", [arg1, arg2, ...]);
Возвращает переданную строку формата с выполненными заменами:
%n- имя шпиона («шпион» по умолчанию)
%c- количество вызовов шпиона в словах («один раз», «дважды» и т. д.)
%C- список строковых представлений вызовов шпиона, каждый вызов с префиксом из новой строки и четырёх пробелов
%t- список значений
thisчерез запятую, с которыми вызывался шпион %n- отформатированное значение n-го аргумента, переданного методу
printf %*- список аргументов (кроме строки формата) через запятую, переданных методу
printf %D- многострочный список аргументов, полученных всеми вызовами шпиона
© 2010–2022 Christian Johansen
Licensed under the BSD License.
https://sinonjs.org/releases/v12/spies