Sinon: Песочница выдает ошибку "не удается заглушить несуществующее собственное свойство"

Созданный на 18 авг. 2017  ·  14Комментарии  ·  Источник: sinonjs/sinon

Я только что попробовал обновить версию с 2.4.1 до 3.2.1 и столкнулся со следующей проблемой. Этот код работает в 2.4.1:

        const spy = sandbox.spy();
        sandbox.stub(window, 'google').value({
            maps: {
                LatLng: x => x,
                Map: spy
            }
        });

Но в 3.2.1 выдается исключение: TypeError: Cannot stub non-existent own property google

Это не упоминается в руководстве по

Bug Regression

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

~ Спасибо за восстановление этого поведения. ~

Хотел добавить вариант использования, который поддерживает заглушку несуществующих свойств.

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

sandbox.stub(serverSecrets, 'the_key_i_need_set').value(fakeValue) - очень ясный способ передать это. Хорошо, что я получаю такое же поведение, _ хотя я не знаю во время выполнения, установлен ли ключ_.

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

Относится к № 1512.

Если свойство не существует, вам не нужно добавлять его в песочницу. Просто перезапишите его. Но да, если это работало раньше, и мы прямо не сказали, что это должно измениться, то это регресс.

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

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

Приятная вещь в добавлении свойства в песочницу заключается в том, что sinon затем помогает мне поддерживать чистоту моей глобальной тестовой среды между каждым тестом с помощью sandbox.restore() . Это чрезвычайно полезная функция, особенно при работе со сторонними библиотеками, такими как Google Maps, где я не контролирую API. Было бы здорово, если бы его можно было заставить работать в линейке 3.x.

Также я только что заметил, что совершил грех, не приведя полный пример. Моя песочница создается в формате 2.4.1:

let sandbox;

before(() => { sandbox = sinon.sandbox.create(); })
afterEach(() => { sandbox.restore(); })

Не уверен, что это важно; извиняюсь за то, что не предоставил его раньше.

Я думаю, что в сценариях, подобных описанному в @ZebraFlesh , я бы предпочел, чтобы текстовое приспособление было более явным.

// not so explicit, doesn't work with [email protected]
beforeEach(function() {
    const spy = sandbox.spy();
    sandbox.stub(window, 'google').value({
        maps: {
            LatLng: x => x,
            Map: spy
        }
    }); 
});
// more explicit, works with sinon<strong i="9">@2</strong>, sinon<strong i="10">@3</strong>
function setGoogleMapsFixture(sandbox) {
    window.google = {
        maps: {
            LatLng: x => x,
            Map: sandbox.spy()
        }
    };
}

function removeGoogleMapsFixture() {
    delete window.google;
}

beforeEach(function() {
    setGoogleMapsFixture(sandbox)
});

// not using afterEach, as this only needs to happen
// after the last test in this block is run
after(function() {
    removeGoogleMapsFixture();
});

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

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

Хотя я признаю, что это может быть удобно в некоторых сценариях (например, описанном @ZebraFlesh), я думаю, что заглушка несуществующих собственных свойств может привести к ошибкам в тестах, где тест проходит, потому что автор неправильно ввел имя существующее имущество они намеревались заглушить. Мы должны стремиться к тому, чтобы исключить возможность ошибок, где это возможно, но не слишком ограничительно.

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

@mroderick Я согласен с вами в том, что это может привести к меньшему количеству ошибок, но мы уже поддерживаем это для обычных заглушек. Если мы должны прекратить поддерживать такое поведение, нам нужно удалить его и там, чтобы быть последовательными. Было бы странно поддерживать эту функцию только вне песочниц, так как песочницы обычно _добавляют_ некоторые возможности. А удаление опоры - это нарушение работы, поэтому также потребуется большая неровность.

Так что либо:

  • немедленно удалите галочку для песочниц, чтобы исправить эту критическую функцию

или / и (?)

  • удалить функциональность как для обычных, так и для изолированных заглушек

    • выпустить новую основную версию с обновленной документацией

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

Я думаю, это хорошо работает, если ваш прибор никогда не меняется в зависимости от ваших тестов. Однако мой прибор работает. Простой пример охватывает как успешные, так и неудачные случаи:

it('handles the success case', () => {
        const spy = sandbox.spy();
        sandbox.stub(window, 'google').value({
            maps: {
                LatLng: x => x,
                Map: spy
            }
        });
        // ... test, including asserting that the spy was called
});

it('handles the failure case', () => {
        const msg = 'test error';
        sandbox.stub(window, 'google').value({
            maps: {
                LatLng: x => x,
                Map: sandbox.stub().throws(new Error(msg))
            }
        });
        // ... test, ignoring spy calls and instead focusing on error handling
});

Преимущество поведения в 2.x состоит в том, что все правильно очищается после каждого теста с помощью sandbox.restore() . Используя более явный пример настройки фикстуры, описанный выше, я полагаю, вы могли бы удалить несобственное свойство в хуке afterEach для достижения того же эффекта.

Чтобы решить проблему внесения потенциальных ошибок из-за непреднамеренного ввода имени существующего собственного свойства, sinon может изменить общедоступный API:

  • stub.ownValue() : заглушает только собственные свойства, выбрасывает несобственные свойства
  • stub.value() : заглушает только чужие свойства, выбрасывает собственные свойства

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

Это очень во многом связано с обсуждением в # 1508 (хотя оно имеет дело с обычными заглушками) h, ​​где @lucasfcosta придерживается противоположной точки зрения - что мы _не должны бросать_ для свойств undefined . Что бы мы ни выбрали, я твердо верю, что нам нужно быть последовательными в API заглушек для обычных заглушек и песочниц. Мы не должны поддерживать его ни в одном случае, ни в другом.

Прямо сейчас ситуация такова:

  • обычные заглушки использовались для вставки в 1.x, но это изменилось в 2.0 и больше не бросает
  • песочницы не использовал закидывать, но начал закидывать в 3.1 (?)

Итак, какое-то время у нас был паритет функций, но потом мы снова его потеряли ... Я не думаю, что этот зигзаг очень полезен для пользователей, поэтому мы должны обсудить это. Хотя я согласен с Морганом в том, что это может сделать для более конкретных тестов, мне не нравится отказываться от поведения для двух основных выпусков, а затем повторно добавлять его снова. Я думаю, что было бы меньше всего шума (исправления для клиентов, вопросы / проблемы на этом трекере), чтобы вернуть эту регрессию.

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

before(function() {
  window.google = 'This is a placeholder for sinon to overwrite.';
});

after(function() {
  delete window.google;
});

Это позволяет коду синона оставаться неизменным.

Регрессия против плохой документации

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

@fearphage Сохранение статус-кво означает, что заглушка несуществующих полей является неподдерживаемым поведением для песочниц, в то время как это поддерживается поведением для обычных заглушек. Разве не прискорбно, что два набора функций не совпадают?

Постановление реализовано в №1557.

Я прочитал различные темы и могу понять, почему это произошло, но это настоящая боль в Typescript, где у вас часто есть функции, реализованные на прототипе класса, и в этом случае sinon плюет на манекен, даже если все выглядит нормально type мудрый (поскольку keyof YourType радостью разрешит все общедоступные функции, которые определены далее по цепочке прототипов).

Я понимаю, что Typescript, вероятно, не является приоритетом для вас, ребята, но даже в JS кажется нелогичным, что myObject.callMe() будет выполняться идеально, а sinon.stub(myObject, "callMe") в этом случае не будет. Я бы предпочел не идти и исследовать, как этот конкретный объект был собран, просто чтобы я знал, как его заглушить.

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

Если вы получаете сообщение о том, что метод не определен для объекта, вы знаете, что ошибка, вероятно, связана с прототипом. Затем прямое изменение объекта с помощью myObject.callMe = sinon.stub(); не кажется таким уж хлопотным ИМХО ... Должно также избавить вас от создания функций очистки / разрыва, поскольку прототип никогда не менялся.

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

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

~ Спасибо за восстановление этого поведения. ~

Хотел добавить вариант использования, который поддерживает заглушку несуществующих свойств.

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

sandbox.stub(serverSecrets, 'the_key_i_need_set').value(fakeValue) - очень ясный способ передать это. Хорошо, что я получаю такое же поведение, _ хотя я не знаю во время выполнения, установлен ли ключ_.

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

Смежные вопросы

fearphage picture fearphage  ·  4Комментарии

stephanwlee picture stephanwlee  ·  3Комментарии

NathanHazout picture NathanHazout  ·  3Комментарии

akdor1154 picture akdor1154  ·  4Комментарии

brettz9 picture brettz9  ·  3Комментарии