Sinon: Este valor de Spy não aponta para a instância ao espiar o construtor

Criado em 9 fev. 2018  ·  10Comentários  ·  Fonte: sinonjs/sinon

Este snippet funciona bem com o Sinon 2.0.0, mas falha com o 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);
});

Parece que o objeto thisValues[0] é um proxy e não se refere à instância real de some .

Este é o erro do 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

Comentários muito úteis

Mesmo que não seja comumente usado, ou pelo menos não seja comumente relatado, gostaria de ter essa regressão corrigida.

Todos 10 comentários

Este é um bom candidato para usar git bisect para estabelecer quando o comportamento foi alterado, o que pode dar alguma pista se a mudança foi intencional ou não (um recurso) ou não (um bug).

Não deve ser tão difícil transformar o exemplo @ PVince81 fornecido em um pequeno script de teste que pode ser usado por git bisect run .

Se você não sabe como usar git bisect , esta é uma excelente oportunidade para subir de nível!

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

Oh, eu adoro dividir! Eu vou cuidar disso ..

Vamos lá: 911c498dc14dc4034ba019526bf58f8b24d77da0 O espião passa chamando com new (# 1626)

Obrigado por fazer isso, @ PVince81! Uma correção também pode querer inspecionar o # 1265, conforme aborda quais mudanças são necessárias para apoiar a espionagem do construtor.

Quando um objeto não é criado com new , este método é chamado, o que altera o conteúdo de thisValue e por extensão thisValues . Em contraste, o método chamado quando new é usado deixa thisValue inalterado.

considerando que nosso código tem apenas um único uso disso, eu ficaria tentado a ir pelo caminho mais rápido e alterar nosso único teste que acionou isso, pois não tenho tempo para envolver minha cabeça em torno dos internos do sinon e não me sinto qualificado para fazer alterações potencialmente importantes

já que poucas pessoas parecem ter reclamado sobre esse problema, talvez as pessoas geralmente não testem dessa forma e uma correção não valha a pena (apenas uma observação, para os mantenedores decidirem)

Mesmo que não seja comumente usado, ou pelo menos não seja comumente relatado, gostaria de ter essa regressão corrigida.

Encontrou o mesmo problema, há algum plano para consertar isso?

@ ivan-zakharchuk Se ninguém for voluntário, não há planos, não. Se você quiser consertar, há um próximo passo natural que pode ser dado ;-)

Este é o cometimento ofensivo: https://github.com/sinonjs/sinon/issues/1683#issuecomment -364794930

Só para dizer, passei muito tempo tentando escrever uma correção para isso, mas não tive sucesso. É um pesadelo de valores de this . O problema principal parece ser que new ing a função fornecida aqui cria inerentemente um novo this , enquanto thisValues[0] (como usado na postagem original) se refere a this criado pelo new no próprio teste (ou seja, o var some = new window.SomeClass(); ) - muito confuso, eu sei.

Essencialmente, consertar isso significa tentar ter as duas coisas - chamar new absolutamente significa um novo this , mas temos que chamá-lo duas vezes (ou seja, um no teste do OP e um em proxy-invoke.js ) para satisfazer ES6. Então você sempre vai acabar com dois this es. A única coisa que consegui pensar foi em vincular as funções de um this ao outro, mas isso era muito hacky até mesmo para isso e quebrou algumas outras coisas.

Espero que o acima faça sentido, sinta-se à vontade para corrigir / solicitar esclarecimentos. Veja aqui uma atualização sobre o que a palavra-chave new realmente faz - TLDR ela cria um novo objeto e o torna this , qualquer que seja o contexto.

De qualquer forma, uma coisa que notei foi que 911c498 (o commit que introduziu a regressão) não inclui um teste cobrindo o problema que ele aborda - o requisito de usar new com classes ES6. Isso provavelmente se deve ao fato de as opções de linting para os testes não permitirem a palavra-chave class , pois atendem apenas ao ES5. Eu tenho um commit adicionando um teste para que qualquer correção futura para o problema atual não desfaça a correção em 911c498 - posso PR se houver interesse.

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

kbirger picture kbirger  ·  3Comentários

zimtsui picture zimtsui  ·  3Comentários

fearphage picture fearphage  ·  4Comentários

fearphage picture fearphage  ·  3Comentários

brettz9 picture brettz9  ·  3Comentários