Sinon: Spy's thisValue ne pointant pas vers l'instance lors de l'espionnage du constructeur

Créé le 9 févr. 2018  ·  10Commentaires  ·  Source: sinonjs/sinon

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()')
Bug Medium Help wanted Regression hacktoberfest pinned

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.

Tous les 10 commentaires

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.

Cette page vous a été utile?
0 / 5 - 0 notes

Questions connexes

NathanHazout picture NathanHazout  ·  3Commentaires

stevenmusumeche picture stevenmusumeche  ·  3Commentaires

zimtsui picture zimtsui  ·  3Commentaires

andys8 picture andys8  ·  4Commentaires

ljian3377 picture ljian3377  ·  3Commentaires