Шпионы
Введение
Что такое шпион для тестирования?
Шпион для тестирования — это функция, которая записывает аргументы, возвращаемое значение, значение 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- имя шпиона "spy" по умолчанию
%c- количество вызовов шпиона в словах ("один раз", "дважды" и т.д.)
%C- список строковых представлений вызовов шпиона, каждый вызов с префиксом новой строки и четырьмя пробелами
%t- список значений
this, на которых был вызван шпион, через запятую %n- отформатированное значение n-го аргумента, переданного в
printf %*- список аргументов (кроме строки формата) передаваемых в
printf, через запятую %D- многострочный список аргументов, полученных всеми вызовами шпиона
© 2010–2022 Christian Johansen
Licensed under the BSD License.
https://sinonjs.org/releases/v13/spies