Spec-Zone.ru › Sinon.JS 5

Шпионы

Введение

Что такое шпион для тестирования?

Шпион для тестирования — это функция, которая записывает аргументы, возвращаемое значение, значение this и брошенное исключение (если таковое имеется) для всех своих вызовов. Существует два типа шпионов: некоторые являются анонимными функциями, а другие оборачивают методы, которые уже существуют в тестируемой системе.

Создание шпиона как анонимной функции

Когда поведение проверяемой функции не проверяется, можно использовать шпиона-анонимную функцию. Шпион ничего не сделает, кроме как запишет информацию о своих вызовах. Типичный случай использования такого шпиона — проверка того, как функция обрабатывает обратный вызов, как в следующем упрощённом примере:

"test should call subscribers on publish": function () {
    var callback = sinon.spy();
    PubSub.subscribe("message", callback);

    PubSub.publishSync("message");

    assertTrue(callback.called);
}

Использование шпиона для оборачивания существующего метода

sinon.spy(object, "method") создаёт шпиона, который оборачивает существующую функцию object.method. Шпион будет вести себя точно так же, как и исходный метод (включая использование в качестве конструктора), но у вас будет доступ к данным обо всех вызовах. Ниже приведён несколько искусственно созданный пример:

{
    setUp: function () {
        sinon.spy(jQuery, "ajax");
    },

    tearDown: function () {
        jQuery.ajax.restore(); // Unwraps the spy
    },

    "test should inspect jQuery.getJSON's usage of jQuery.ajax": function () {
        jQuery.getJSON("/some/resource");

        assert(jQuery.ajax.calledOnce);
        assertEquals("/some/resource", jQuery.ajax.getCall(0).args[0].url);
        assertEquals("json", jQuery.ajax.getCall(0).args[0].dataType);
    }
}

Создание шпионов: 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.

API шпионов

Шпионы предоставляют богатый интерфейс для проверки их использования. В приведенных выше примерах показана calledOnce булевская свойство, а также getCall метод и args свойство возвращаемого объекта. Существует три способа проверки данных вызовов.

Рекомендуемый подход — использовать метод calledWith шпиона (и аналогичные методы), так как это позволяет сделать ваш тест менее специфичным относительно того, какой вызов что сделал и так далее. Он вернёт true , если шпион когда-либо вызывался с указанными аргументами.

"test should call subscribers with message as first argument" : function () {
    var message = 'an example message';
    var spy = sinon.spy();

    PubSub.subscribe(message, spy);
    PubSub.publishSync(message, "some payload");

    assert(spy.calledWith(message));
}

Если вы хотите быть конкретнее, вы можете напрямую проверить первый аргумент первого вызова. Существует два способа достижения этого:

"test should call subscribers with message as first argument" : function () {
    var message = 'an example message';
    var spy = sinon.spy();

    PubSub.subscribe(message, spy);
    PubSub.publishSync(message, "some payload");

    assertEquals(message, spy.args[0][0]);
}
"test should call subscribers with message as first argument" : function () {
    var message = 'an example message';
    var spy = sinon.spy();

    PubSub.subscribe(message, spy);
    PubSub.publishSync(message, "some payload");

    assertEquals(message, spy.getCall(0).args[0]);
}

В первом примере используется двумерный массив args напрямую в шпионе, а во втором примере извлекается первый объект вызова, а затем обращается к его массиву args. Какой из них использовать — дело вкуса, но рекомендуемый подход — использовать spy.calledWith(arg1, arg2, ...), если нет необходимости в высокоспецифичных тестах.

API

Объекты шпионов возвращаются из sinon.spy(). При шпионении на существующие методы с помощью sinon.spy(object, method), следующие свойства и методы также доступны для object.method.

Свойства

spy.withArgs(arg1[, arg2, ...]);

Создаёт шпиона, который записывает вызовы только в том случае, если полученные аргументы соответствуют аргументам, переданным withArgs. Это полезно для большей выразительности в ваших утверждениях, где вы можете получить доступ к шпиону с тем же вызовом.

"should call method once with each argument": function () {
    var object = { method: function () {} };
    var spy = sinon.spy(object, "method");

    object.method(42);
    object.method(1);

    assert(spy.withArgs(42).calledOnce);
    assert(spy.withArgs(1).calledOnce);
}

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-й вызов.

Доступ к отдельным вызовам помогает в более подробной проверке поведения, когда шпион вызывается более одного раза.

sinon.spy(jQuery, "ajax");
jQuery.ajax("/stuffs");
var spyCall = jQuery.ajax.getCall(0);

assertEquals("/stuffs", spyCall.args[0]);

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–2018 Christian Johansen
Licensed under the BSD License.
http://sinonjs.org/releases/v5.1.0/spies

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API