Spec-Zone.ru › Sinon.JS 1

Шпионы

Введение

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

Шпион для тестирования — это функция, которая записывает аргументы, возвращаемое значение, значение 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 boolean, а также метод 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");
    spy.withArgs(42);
    spy.withArgs(1);

    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.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/v1.17.7/spies

Spec-Zone.ru

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