Sinon: Обертывание геттеров и сеттеров ES5

Созданный на 3 мар. 2012  ·  23Комментарии  ·  Источник: sinonjs/sinon

var o = {
  get foobar() { return 'foobar' },
  set foobar(s) { throw 'bzzt!' },
  foo: function() { return 'foo' },
  bar: 'bar'
}; // -> { foobar: [Getter/Setter], foo: [Function], bar: 'bar' }

sinon.mock(o).expects('foobar').returns('woohoo'); // doesn't because sinon.wrapMethod() does an object[property] which accesses the getter which returns a string

Для поддержки геттеров и сеттеров вам нужно сделать Object.getOwnPropertyDescriptor(obj, prop) для объекта, а затем рекурсивный Object.getPrototypeOf(obj) если он не существует, в дескрипторе есть 'get' и 'set' свойство, в котором они определены.

Но вы можете смоделировать только геттер, или только сеттер, или и то, и другое, так как же это указать? Некоторые варианты:

mock(o).expects('foobar'); // ambiguous, the setter? getter? or both?
mock(o).expects('get foobar'); // ambiguous, there may be a legitimate property named "get foobar"
mock(o).expectsGet('foobar'); // clear but more code in Sinon and more to document ?
mock(o).expectsSet('foobar'); // ditto

А также, есть ли у вас соглашение о работе с функциями, которые могут отсутствовать в текущей среде? Что должно произойти, если кто-то попытается сделать это в IE6?

Самый полезный комментарий

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

Все 23 Комментарий

Глядя на ваши примеры, я не совсем уверен, что имитирующие геттеры - хорошая практика тестирования - я бы предположил, что простая установка для свойства некоторого значения на время теста в большинстве случаев будет иметь большое значение (?)

В любом случае, что, если заглушка является объектом, а не функцией, она будет рассматриваться как дескриптор свойства? Что-то вроде:

stub(o, "foobar", { get: function () { return 42; } });

Я не знаю, как оправдать ваши ожидания. Но, как я уже сказал, но стоит ли ставить ложные ожидания при поиске недвижимости? Мне кажется, что если вам это нужно, может быть, это должны быть «настоящие» методы?

Пример был упрощен. Настоящий код, над которым я пытался это сделать, назывался get identifier который складывал вместе несколько вещей, некоторые из которых были взяты из мест, о которых я не хотел беспокоиться в тесте, я просто хотел подтвердить, что Был получен доступ к x.identifier а затем вы можете контролировать то, что было возвращено. На данный момент я выберу getIdentifier() что нормально, но, учитывая, что мы, возможно, увидим больше геттеров и сеттеров в будущем для вычисляемых свойств, это может быть то, с чем Sinon могла бы / должна справиться?

Все еще не определился с этим. Дадим ему немного отдохнуть, а потом решим. Если у вас есть дополнительные отзывы / предложения, не стесняйтесь записывать их здесь.

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

На данный момент я не вижу смысла в поддержке геттеров и сеттеров в Sinon.

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

+1
Я тоже скучаю по нему. Это было бы особенно полезно при использовании с компонентами, которые работают как абстракции с геттерами над некоторыми базовыми ресурсами, такими как файлы или объекты базы данных. Было бы неплохо иметь возможность заглушить эти геттеры.

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

+1 за эту функцию!

: +1: Я тоже просто почувствовал потребность в этой функции.

: +1: Это нужно заново открыть. Это особенно важно, особенно с появлением ES6. Мне нравится вариант expectsGet .

+1 Я полностью согласен с @simonzack

+1

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

Закрывает ли https://github.com/mroderick/wrapple этот пробел для вас?

В настоящее время я довольно широко использую wrapple и забыл комментировать эту проблему. Это, вероятно, означает, что, как вы говорите, wrapple закрыл брешь.

+1 только что наткнулся на синон, не поддерживающую издевательство над геттером

Привет, @derwaldgeist , вы используете последнюю версию

Последний поддерживает заглушки геттеров как с sandboxes и с sinon.stub .

Все, что вам нужно сделать, это использовать функцию get , например:

var myObj = {
    prop: "foo"
};

createStub(myObj, "prop").get(function getterFn() {
    return "bar";
});

myObj.prop // "bar"

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

Спасибо, что вернулись так быстро, очень признательны.
Однако я не нашел, как можно восстановить геттер, который был определен таким образом? Я даже посмотрел исходный код sinon и не увидел механизма, который сохраняет исходный получатель при вызове get ().

Привет @derwaldgeist!

Действительно, можно восстановить геттеры, даже если они не были определены до того, как были заглушены. Все, что вам нужно сделать, это вызвать метод restore в созданной заглушке, например:

var myObj = {
    prop: "foo"
};

var stub = createStub(myObj, "prop");

stub.get(function getterFn() {
    return "baz";
});

myObj.prop // "baz"

stub.restore();

myObj.prop // "foo"

Мы добавляем этот метод restore либо в сам метод stub (при заглушке нефункционального свойства), либо в служебную программу wrapMethod .

Вау, это было быстро. Я пробовал это:

 const stub = sinon.stub(myObj, 'prop');
 stub.get(() => ({}));
  ...
 stub.restore();

но при выполнении restore () он говорит: Cannot redefine property: prop

Откуда появился ваш метод createStub ?

@derwaldgeist Я получил это из теста, извините, забыл отредактировать. Но в любом случае это то же самое, что и sinon.stub .

Подскажите, какую версию sinon вы используете, чтобы я мог ее проверить?

Я думаю, что, возможно, вы еще не используете последнюю версию, в которой мы исправили ошибку, из-за которой вы не могли восстановить свойства из-за того, что они были определены без configurable: true и поэтому мы не могли изменить их дескрипторы.

Я вижу то же, что и @derwaldgeist. Я _ думаю_, что использую v4, но некоторые другие deps использовали v1.7, поэтому я не уверен, что _ на самом деле_ используется. Я не видел sinon.version где я мог бы проверить во время выполнения.

@ jshado1 Если вы хотите узнать, какая у вас основная версия, вы можете обратиться к журналу изменений или руководству по миграции и проверить наличие критических изменений. Для версии 4 вы можете утверждать, что sinon.stub({}, 'nonExistingProperty') выбрасывает

Была ли эта страница полезной?
0 / 5 - 0 рейтинги