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()')
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.
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.