Cet extrait de code fonctionne correctement avec Sinon 2.0.0 mais échoue avec 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);
});
Il semble que l'objet thisValues[0]
est un proxy et ne fait pas référence à l'instance réelle de some
.
C'est l'erreur avec Sinon 4.2.2:
Expected undefined to equal 1
TypeError: undefined is not a function (evaluating 'spy.thisValues[0].getCounter()')
C'est un bon candidat pour utiliser git bisect
pour établir quand le comportement a été changé, ce qui pourrait donner des indices pour savoir si le changement était intentionnel (une fonctionnalité) ou non (un bogue).
Il ne devrait pas être si difficile de transformer l'exemple @ PVince81 fourni en un petit script de test pouvant être utilisé pour git bisect run
.
Si vous ne savez pas comment utiliser git bisect
, c'est une excellente occasion de passer au niveau supérieur!
http://www.marclittlemore.com/how-to-find-bugs-using-git-bisect-with-this-easy-guide/
Oh, j'adore couper en deux! Je vais m'occuper de ça ...
On y va: 911c498dc14dc4034ba019526bf58f8b24d77da0 L'espion passe par un appel avec new
(# 1626)
Merci d'avoir fait ça, @ PVince81! Un correctif peut également vouloir inspecter # 1265, car il concerne les modifications nécessaires pour prendre en charge l'espionnage des constructeurs.
Lorsqu'un objet n'est pas créé avec new
, cette méthode est appelée, ce qui modifie le contenu de thisValue
et par extension thisValues
. En revanche, la méthode appelée quand new est utilisée laisse thisValue
inchangé.
étant donné que notre code n'a qu'une seule utilisation de celui-ci, je serais plutôt tenté d'emprunter la voie rapide et de changer notre test unique qui a déclenché cela car je n'ai pas le temps de me concentrer sur les éléments internes de sinon et je ne me sens pas qualifié pour apporter des modifications potentiellement importantes
comme peu de gens semblent s'être plaints de ce problème, peut-être que les gens ne testent généralement pas de cette façon et qu'un correctif n'en vaut pas la peine (juste une observation, c'est aux responsables de décider)
Même si ce n'est pas couramment utilisé, ou du moins pas couramment signalé, j'aimerais que cette régression soit corrigée.
Avez-vous rencontré le même problème, est-il prévu de résoudre ce problème?
@ ivan-zakharchuk Si personne ne fait du bénévolat, il n'y a pas de plans, non. Si vous voulez qu'il soit réparé, il y a une prochaine étape naturelle qui pourrait être franchie ;-)
Voici le commit incriminé: https://github.com/sinonjs/sinon/issues/1683#issuecomment -364794930
Juste pour dire, j'ai passé un long moment à essayer d'écrire un correctif pour cela, mais sans succès. C'est un cauchemar de valeurs this
. Le problème principal semble être que new
la fonction fournie ici crée intrinsèquement un tout nouveau this
, alors que thisValues[0]
(tel qu'utilisé dans le message d'origine) fait référence au this
créé par le new
dans le test lui-même (c'est-à-dire le var some = new window.SomeClass();
) - très déroutant je sais.
Essentiellement, corriger cela signifie essayer de jouer dans les deux sens - appeler new
signifie absolument un nouveau this
, mais nous devons l'appeler deux fois (c'est-à-dire un dans le test de OP et un dans proxy-invoke.js
) pour satisfaire ES6. Donc, vous allez toujours vous retrouver avec deux this
es. La seule chose à laquelle je pouvais penser était de lier les fonctions d'un this
à l'autre, mais c'était trop piraté même pour cela et a cassé quelques autres choses.
J'espère que ce qui précède a du sens, n'hésitez pas à corriger / demander des éclaircissements. Voir ici pour un rappel sur ce que fait réellement le mot-clé new
- TLDR il crée un nouvel objet et le rend this
, quel que soit le contexte.
Quoi qu'il en soit, une chose que j'ai remarquée est que 911c498 (le commit qui a introduit la régression) n'inclut pas de test couvrant le problème qu'il aborde - l'obligation d'utiliser new
avec les classes ES6. Ceci est probablement dû au fait que les options de linting pour les tests n'autorisent pas le mot-clé class
car elles ne concernent que ES5. J'ai un commit ajoutant un test afin que tout correctif futur pour le problème actuel ne corrige pas le correctif dans 911c498 - je peux le PR s'il y a un intérêt.
Commentaire le plus utile
Même si ce n'est pas couramment utilisé, ou du moins pas couramment signalé, j'aimerais que cette régression soit corrigée.