Spec-Zone.ru › Sinon.JS 2

Шпионы

Введение

Что такое шпион-тест?

Шпион-тест — это функция, которая записывает аргументы, возвращаемое значение, значение 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.alwaysCalledWith(arg1, arg2, ...);

Возвращает true , если шпион всегда вызывался с указанными аргументами (и, возможно, другими).

spy.calledWithExactly(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.reset()

Сбрасывает состояние шпиона.

spy.restore()

Заменяет шпиона исходным методом. Доступно только если шпион заменил существующий метод.

spy.printf("format string", [arg1, arg2, ...])

Возвращает переданную строку формата с выполненными заменами:

%n
имя шпиона по умолчанию "шпион")
%c
количество вызовов шпиона, в словах ("один раз", "дважды" и т. д.)
%C
список строковых представлений вызовов шпиона, каждый вызов с префиксом новой строки и четырьмя пробелами
%t
список значений this, перечисленных через запятую, на которые был вызван шпион
%n
форматированное значение n-го аргумента, переданного printf
%*
список (не строковых) аргументов, переданных printf, перечисленных через запятую

Индивидуальные вызовы шпиона

var spyCall = spy.getCall(n)

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

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

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

spyCall.calledOn(obj);

Возвращает true , если obj был this для этого вызова. calledOn также принимает соответствие spyCall.calledOn(sinon.match(fn)) (см. соответствия).

spyCall.calledWith(arg1, arg2, ...);

Возвращает true , если вызов получил предоставленные аргументы (и, возможно, другие).

spyCall.calledWithExactly(arg1, arg2, ...);

Возвращает true , если вызов получил предоставленные аргументы и не другие.

spyCall.calledWithMatch(arg1, arg2, ...);

Возвращает true , если вызов получил соответствующие аргументы (и, возможно, другие). Это ведет себя так же, как spyCall.calledWith(sinon.match(arg1), sinon.match(arg2), ...).

spyCall.notCalledWith(arg1, arg2, ...);

Возвращает true , если вызов не получил предоставленные аргументы.

spyCall.notCalledWithMatch(arg1, arg2, ...);

Возвращает true , если вызов не получил соответствующие аргументы. Это ведет себя так же, как spyCall.notCalledWith(sinon.match(arg1), sinon.match(arg2), ...).

spyCall.threw();

Возвращает true , если вызов бросил исключение.

spyCall.threw("TypeError");

Возвращает true , если вызов бросил исключение указанного типа.

spyCall.threw(obj);

Возвращает true , если вызов бросил указанный объект исключения.

spyCall.thisValue

Значение вызова this.

spyCall.args

Массив полученных аргументов.

spyCall.exception

Брошенное исключение, если таковое имеется.

spyCall.returnValue

Возвращаемое значение.]}]}

© 2010–2017 Christian Johansen
Licensed under the BSD License.
http://sinonjs.org/releases/v2.4.1/spies

Spec-Zone.ru

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