Sinon: Шпион thisValue не указывает на экземпляр при слежке за конструктором

Созданный на 9 февр. 2018  ·  10Комментарии  ·  Источник: sinonjs/sinon

Этот фрагмент отлично работает с Sinon 2.0.0, но не работает с Sinon 4.2.2:

it('returns correct thisValue', function() {
    window.SomeClass = function() {
        this.counter = 0;
        this.inc = function() {
            this.counter++;
        };
        this.getCounter = function() {
            return this.counter;
        };
    };

    var spy = sinon.spy(window, 'SomeClass');
    var some = new window.SomeClass();
    some.inc();

    expect(spy.thisValues[0].counter).toEqual(1);
    expect(spy.thisValues[0].getCounter()).toEqual(1);
    some.inc();
    expect(spy.thisValues[0].counter).toEqual(2);
    expect(spy.thisValues[0].getCounter()).toEqual(2);
});

Похоже, что объект thisValues[0] является прокси-сервером и не относится к фактическому экземпляру some .

Это ошибка Sinon 4.2.2:

Expected undefined to equal 1
TypeError: undefined is not a function (evaluating 'spy.thisValues[0].getCounter()')
Bug Medium Help wanted Regression hacktoberfest pinned

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

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

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

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

Не должно быть так сложно превратить предоставленный пример @ PVince81 в небольшой тестовый скрипт, который можно использовать для git bisect run .

Если вы не знаете, как использовать git bisect , это отличная возможность для повышения уровня!

http://www.marclittlemore.com/how-to-find-bugs-using-git-bisect-with-this-easy-guide/

О, я люблю делить пополам! Я позабочусь об этом ..

Начнем: 911c498dc14dc4034ba019526bf58f8b24d77da0 Шпион проходит через вызов с new (# 1626)

Спасибо за это, @ PVince81! Исправление может также потребовать проверки # 1265, поскольку оно касается того, какие изменения необходимы для поддержки слежения за конструктором.

Если объект не создан с помощью new , вызывается этот метод , который изменяет содержимое thisValue и путем расширения thisValues . Напротив, метод, вызываемый при использовании new, оставляет thisValue без изменений.

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

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

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

Обнаружена та же проблема, есть ли планы по ее устранению?

@ ivan-zakharchuk Если никто не занимается волонтерством, нет никаких планов, нет. Если вы хотите, чтобы это было исправлено, можно сделать следующий естественный шаг ;-)

Это оскорбительная фиксация: https://github.com/sinonjs/sinon/issues/1683#issuecomment -364794930

Чтобы сказать, я долгое время пытался написать исправление для этого, но безуспешно. Это кошмар значений this . Основная проблема, похоже, заключается в том, что new указанная здесь функция, по своей сути создает новый this , тогда как thisValues[0] (как используется в исходном сообщении) относится к this создано new в самом тесте (то есть var some = new window.SomeClass(); ) - я знаю, очень запутанно.

По сути, исправить это означает попытаться использовать оба варианта - вызов new абсолютно означает новый this , но мы должны вызвать его дважды (то есть один в тесте OP и один в proxy-invoke.js ), чтобы удовлетворить ES6. Так что у вас всегда будет два this es. Единственное, что я мог придумать, - это привязать функции из одного this к другому, но это было слишком хакерским делом даже для этого и сломало несколько других вещей.

Я надеюсь, что вышеизложенное имеет смысл, пожалуйста, исправьте / запросите разъяснения. См. Здесь, чтобы узнать, что на самом деле делает ключевое слово new - TLDR создает новый объект и делает его this вне зависимости от контекста.

Во всяком случае, я заметил одну вещь: 911c498 (коммит, который привел к регрессии) не включает тест, охватывающий проблему, которую он решает, - требование использовать new с классами ES6. Вероятно, это связано с тем, что параметры линтинга для тестов не позволяют использовать ключевое слово class поскольку они предназначены только для ES5. У меня есть коммит, добавляющий тест, так что любое будущее исправление текущей проблемы не отменяет исправление в 911c498 - я могу PR, если есть интерес.

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