Spec-Zone.ru › Sinon.JS 6
Эти документы относятся к более старой версии sinon. Хотите перейти к последним документам?

Заглушки

Что такое заглушки?

Заглушки — это функции (шпионы) с предопределённым поведением.

Они поддерживают весь API шпионов для тестов, а также методы, которые можно использовать для изменения поведения заглушки.

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

Когда использовать заглушки?

Используйте заглушку, когда хотите:

  1. Управлять поведением метода из теста, чтобы заставить код пройти по определённому пути. Примеры включают принудительное выброс ошибки методом для тестирования обработки ошибок.

  2. Когда вы хотите предотвратить прямой вызов конкретного метода (возможно, потому что он вызывает нежелательное поведение, например, XMLHttpRequest или подобное).

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

"test should call all subscribers, even if there are exceptions" : function(){
    var message = 'an example message';
    var stub = sinon.stub().throws();
    var spy1 = sinon.spy();
    var spy2 = sinon.spy();

    PubSub.subscribe(message, stub);
    PubSub.subscribe(message, spy1);
    PubSub.subscribe(message, spy2);

    PubSub.publishSync(message, undefined);

    assert(spy1.called);
    assert(spy2.called);
    assert(stub.calledBefore(spy1));
}

Обратите внимание, как заглушка также реализует интерфейс шпиона. Тест проверяет, что все обратные вызовы были вызваны, а также то, что заглушка, выбрасывающая исключение, была вызвана до одного из других обратных вызовов.

Определение поведения заглушки при последовательных вызовах

Вызов методов определения поведения, таких как returns или throws несколько раз перезаписывает поведение заглушки. Начиная с версии Sinon 1.8, вы можете использовать метод onCall, чтобы заглушка реагировала по-разному при последовательных вызовах.

Обратите внимание, что в версиях Sinon с 1.5 по 1.7 несколько вызовов методов yields* и callsArg* определяют последовательность поведения для последовательных вызовов. Начиная с версии 1.8, эта функциональность была удалена в пользу API onCall.

API заглушек

Свойства

var stub = sinon.stub();

Создаёт анонимную функцию-заглушку

var stub = sinon.stub(object, "method");

Заменяет object.method на функцию-заглушку. Если свойство не является функцией, выбрасывается исключение.

Исходную функцию можно восстановить, вызвав object.method.restore(); (или stub.restore();).

var stub = sinon.stub(object, "method", func);

Это было удалено из v3.0.0. Вместо этого вы должны использовать

stub(obj, 'meth').callsFake(fn)

Доступен кодмод для обновления вашего кода

var stub = sinon.stub(obj);

Заглушает все методы объекта.

Обратите внимание, что обычно лучше заглушать отдельные методы, особенно для объектов, которые вы не понимаете или не контролируете все методы (например, зависимости библиотек).

Заглушение отдельных методов более точно отражает намерения и менее подвержено непредвиденному поведению по мере эволюции кода объекта.

Если вы хотите создать объект-заглушку MyConstructor, но не хотите вызывать конструктор, используйте эту утилитарную функцию.

var stub = sinon.createStubInstance(MyConstructor, overrides);

overrides — это необязательная карта, перезаписывающая созданные заглушки, например:

var stub = sinon.createStubInstance(MyConstructor, {
    foo: sinon.stub().returnsThis()
});

равносильно:

var stub = sinon.createStubInstance(MyConstructor);
stub.foo.returnsThis();

Если предоставленное значение не является заглушкой, оно будет использоваться как возвращаемое значение:

var stub = sinon.createStubInstance(MyConstructor, {
    foo: 3
});

равносильно:

var stub = sinon.createStubInstance(MyConstructor);
stub.foo.returns(3);

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

Заглушает метод только для указанных аргументов.

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

"test should stub method differently based on arguments": function () {
    var callback = sinon.stub();
    callback.withArgs(42).returns(1);
    callback.withArgs(1).throws("name");

    callback(); // No return value, no exception
    callback(42); // Returns 1
    callback(1); // Throws Error("name")
}

stub.onCall(n); Добавлен в v1.8

Определяет поведение заглушки при n-ом вызове. Полезно для тестирования последовательных взаимодействий.

"test should stub method differently on consecutive calls": function () {
    var callback = sinon.stub();
    callback.onCall(0).returns(1);
    callback.onCall(1).returns(2);
    callback.returns(3);

    callback(); // Returns 1
    callback(); // Returns 2
    callback(); // All following calls return 3
}

Существуют методы onFirstCall, onSecondCall, onThirdCall для более естественного чтения определений заглушки.

onCall можно комбинировать со всеми методами определения поведения в этом разделе. В частности, он может использоваться вместе с withArgs.

"test should stub method differently on consecutive calls with certain argument": function () {
    var callback = sinon.stub();
    callback.withArgs(42)
        .onFirstCall().returns(1)
        .onSecondCall().returns(2);
    callback.returns(0);

    callback(1); // Returns 0
    callback(42); // Returns 1
    callback(1); // Returns 0
    callback(42); // Returns 2
    callback(1); // Returns 0
    callback(42); // Returns 0
}

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

stub.onFirstCall();

Псевдоним для stub.onCall(0);

stub.onSecondCall();

Псевдоним для stub.onCall(1);

stub.onThirdCall();

Псевдоним для stub.onCall(2);

stub.reset();

Сбрасывает поведение и историю заглушки.

Это эквивалентно вызову как stub.resetBehavior() , так и stub.resetHistory()

Обновлено в sinon@2.0.0

С sinon@5.0.0

Для удобства вы можете применить stub.reset() ко всем заглушкам, используя sinon.reset()

stub.resetBehavior();

Сбрасывает поведение заглушки до стандартного.

var stub = sinon.stub();

stub.returns(54)

stub(); // 54

stub.resetBehavior();

stub(); // undefined

С sinon@5.0.0

Вы можете сбросить поведение всех заглушек, используя sinon.resetBehavior()

stub.resetHistory();

С sinon@2.0.0

Сбрасывает историю заглушки

var stub = sinon.stub();

stub.called // false

stub();

stub.called // true

stub.resetHistory();

stub.called // false

С sinon@5.0.0

Вы можете сбросить историю всех заглушек, используя sinon.resetHistory()

stub.callsFake(fakeFunction);

Заставляет заглушку вызывать предоставленную fakeFunction при вызове.

var myObj = {};
myObj.prop = function propFn() {
    return 'foo';
};

sinon.stub(myObj, 'prop').callsFake(function fakeFn() {
    return 'bar';
});

myObj.prop(); // 'bar'

stub.returns(obj);

Заставляет заглушку возвращать предоставленное значение.

stub.returnsArg(index);

Заставляет заглушку возвращать аргумент по указанному индексу.

stub.returnsArg(0); заставляет заглушку возвращать первый аргумент.

Если аргумент по указанному индексу недоступен, до sinon@6.1.2, будет возвращено значение undefined; начиная с sinon@6.1.2, будет выброшено исключение TypeError.

stub.returnsThis();

Заставляет заглушку возвращать её this значение.

Полезно для заглушения jQuery-подобных API.

stub.resolves(value);

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

При создании промиса sinon использует метод Promise.resolve. Вам необходимо предоставить полифил в средах, которые не поддерживают Promise. Библиотеку промисов можно переопределить с помощью метода usingPromise.

С sinon@2.0.0

stub.resolvesArg(index);

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

stub.resolvesArg(0); заставляет заглушку возвращать промис, который разрешается первым аргументом.

Если аргумент по указанному индексу недоступен, будет выброшено исключение TypeError.

С sinon@6.1.1

stub.throws();

Заставляет заглушку выбросить исключение (Error).

stub.throws("name"[, "optional message"]);

Заставляет заглушку выбросить исключение с свойством name, установленным в предоставленную строку. Параметр message является необязательным и установит свойство message исключения.

stub.throws(obj);

Заставляет заглушку выбросить предоставленный объект исключения.

stub.throws(function() { return new Error(); });

Заставляет заглушку выбросить исключение, возвращаемое функцией.

stub.throwsArg(index);

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

stub.throwsArg(0); заставляет заглушку выбросить первый аргумент как исключение.

Если аргумент по указанному индексу недоступен, будет выброшено исключение TypeError.

С sinon@2.3.0

stub.rejects();

Заставляет заглушку возвращать промис, который отклоняется исключением (Error).

При создании промиса sinon использует метод Promise.reject. Вам необходимо предоставить полифил в средах, которые не поддерживают Promise. Библиотеку промисов можно переопределить с помощью метода usingPromise.

С sinon@2.0.0

stub.rejects("TypeError");

Заставляет заглушку возвращать промис, который отклоняется исключением указанного типа.

С sinon@2.0.0

stub.rejects(value);

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

С sinon@2.0.0

stub.callsArg(index);

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

stub.callsArg(0); заставляет заглушку вызвать первый аргумент как обратный вызов.

Если аргумент по указанному индексу недоступен или не является функцией, будет выброшено исключение TypeError.

stub.callThrough();

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

var stub = sinon.stub();

var obj = {};

obj.sum = function sum(a, b) {
    return a + b;
};

stub(obj, 'sum');

obj.sum.withArgs(2, 2).callsFake(function foo() {
    return 'bar';
});

obj.sum.callThrough();

obj.sum(2, 2); // 'bar'
obj.sum(1, 2); // 3

stub.callsArgOn(index, context);

Как stub.callsArg(index);, но с дополнительным параметром для передачи контекста this.

stub.callsArgWith(index, arg1, arg2, ...);

Как callsArg, но с аргументами для передачи в обратный вызов.

stub.callsArgOnWith(index, context, arg1, arg2, ...);

Как выше, но с дополнительным параметром для передачи контекста this.

stub.usingPromise(promiseLibrary);

Заставляет заглушку возвращать промисы, используя определённую библиотеку промисов вместо глобальной при использовании stub.rejects или stub.resolves.

var myObj = {
    saveSomething: sinon.stub().usingPromise(bluebird.Promise).resolves("baz");
}

myObj.saveSomething()
    .tap(function(actual) {
        console.log(actual); // baz
    });

С sinon@2.0.0

stub.yields([arg1, arg2, ...])

Аналогично callsArg.

Заставляет заглушку вызвать первый полученный обратный вызов с указанными аргументами (если таковые имеются).

Если метод принимает более одного обратного вызова, необходимо использовать yieldsRight для вызова последнего обратного вызова или callsArg для вызова других обратных вызовов, кроме первого или последнего.

stub.yieldsRight([arg1, arg2, ...])

Как yields, но вызывает последний полученный обратный вызов.

stub.yieldsOn(context, [arg1, arg2, ...])

Как yields, но с дополнительным параметром для передачи контекста this.

stub.yieldsTo(property, [arg1, arg2, ...])

Заставляет шпион вызывать обратный вызов, переданный как свойство объекта шпион.

Как yields, yieldsTo захватывает первый соответствующий аргумент, находит обратный вызов и вызывает его с (необязательными) аргументами.

stub.yieldsToOn(property, context, [arg1, arg2, ...])

Как выше, но с дополнительным параметром для передачи контекста this.

"test should fake successful ajax request": function () {
    sinon.stub(jQuery, "ajax").yieldsTo("success", [1, 2, 3]);

    jQuery.ajax({
        success: function (data) {
            assertEquals([1, 2, 3], data);
        }
    });
}

stub.yield([arg1, arg2, ...])

Вызывает обратные вызовы, переданные в stub, с заданными аргументами.

Если для фикстуры никогда не передавался аргумент-функция, yield выбросит ошибку.

Возвращает массив со всеми значениями возврата обратных вызовов в порядке их вызова, если не было выброшено ошибок.

Также алиас invokeCallback.

stub.yieldTo(callback, [arg1, arg2, ...])

Вызывает обратные вызовы, переданные как свойство объекта в фикстуру.

Как yield, yieldTo захватывает первый соответствующий аргумент, находит обратный вызов и вызывает его с (необязательными) аргументами.

"calling callbacks": function () {
    var callback = sinon.stub();
    callback({
        "success": function () {
            console.log("Success!");
        },
        "failure": function () {
            console.log("Oh noes!");
        }
    });

    callback.yieldTo("failure"); // Logs "Oh noes!"
}

stub.callArg(argNum)

Как yield, но с явным номером аргумента, указывающим, какой обратный вызов вызвать.

Полезно, если функция вызывается с более чем одним обратным вызовом, и нежелательно просто вызвать первый обратный вызов.

"calling the last callback": function () {
    var callback = sinon.stub();
    callback(function () {
        console.log("Success!");
    }, function () {
        console.log("Oh noes!");
    });

    callback.callArg(1); // Logs "Oh noes!"
}

stub.callArgWith(argNum, [arg1, arg2, ...])

Как callArg, но с аргументами.

Асинхронные вызовы

То же самое, что и соответствующие им не асинхронные аналоги, но с отложенным обратным вызовом, который выполняется после обработки всех инструкций в текущем стеке вызовов.

  • В среде Node обратный вызов откладывается с помощью process.nextTick.
  • В браузере обратный вызов откладывается с помощью setTimeout(callback, 0).

Дополнительная информация:

  • https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick,
  • https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop,
  • https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout.
stub.callsArgAsync(index);

Асинхронная версия stub.callsArg(index). См. также Асинхронные вызовы.

stub.callsArgOnAsync(index, context);

Асинхронная версия stub.callsArgOn(index, context). См. также Асинхронные вызовы.

stub.callsArgWithAsync(index, arg1, arg2, ...);

Асинхронная версия stub.callsArgWith(index, arg1, arg2, …). См. также Асинхронные вызовы.

stub.callsArgOnWithAsync(index, context, arg1, arg2, ...);

Асинхронная версия stub.callsArgOnWith(index, context, arg1, arg2, …). См. также Асинхронные вызовы.

stub.yieldsAsync([arg1, arg2, ...]);

Асинхронная версия stub.yields([arg1, arg2, …]). См. также Асинхронные вызовы.

stub.yieldsOnAsync(context, [arg1, arg2, ...]);

Асинхронная версия stub.yieldsOn(context, [arg1, arg2, …]). См. также Асинхронные вызовы.

stub.yieldsToAsync(property, [arg1, arg2, ...]);

Асинхронная версия stub.yieldsTo(property, [arg1, arg2, …]). См. также Асинхронные вызовы.

stub.yieldsToOnAsync(property, context, [arg1, arg2, ...])

Асинхронная версия stub.yieldsToOn(property, context, [arg1, arg2, …]). См. также Асинхронные вызовы.

sinon.addBehavior(name, fn);

Добавление пользовательского поведения. Имя будет доступно как функция в фикстурах, и для вас будет настроена механизм цепочки вызовов (например, вам не нужно ничего возвращать из вашей функции, её значение возврата будет проигнорировано). fn будет передан подставленный экземпляр как первый аргумент, а затем аргументы пользователя.

const sinon = require('sinon');

sinon.addBehavior('returnsNum', (fake, n) => fake.returns(n));

var stub = sinon.stub().returnsNum(42);

assert.equals(stub(), 42);

stub.get(getterFn)

Заменяет новый геттер для этой фикстуры.

var myObj = {
    prop: 'foo'
};

sinon.stub(myObj, 'prop').get(function getterFn() {
    return 'bar';
});

myObj.prop; // 'bar'

stub.set(setterFn)

Определяет новый сеттер для этой фикстуры.

var myObj = {
    example: 'oldValue',
    prop: 'foo'
};

sinon.stub(myObj, 'prop').set(function setterFn(val) {
    myObj.example = val;
});

myObj.prop = 'baz';

myObj.example; // 'baz'

stub.value(newVal)

Определяет новое значение для этой фикстуры.

var myObj = {
    example: 'oldValue',
};

sinon.stub(myObj, 'example').value('newValue');

myObj.example; // 'newValue'

Вы можете восстановить значения, вызвав метод restore.

var myObj = {
    example: 'oldValue',
};

var stub = sinon.stub(myObj, 'example').value('newValue');
stub.restore()

myObj.example; // 'oldValue'

© 2010–2018 Christian Johansen
Licensed under the BSD License.
https://sinonjs.org/releases/v6.3.5/stubs

Spec-Zone.ru

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