Sinon: Spy's thisValue no apunta a la instancia al espiar el constructor

Creado en 9 feb. 2018  ·  10Comentarios  ·  Fuente: sinonjs/sinon

Este fragmento funciona bien con Sinon 2.0.0 pero falla con 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 el objeto thisValues[0] es un proxy y no se refiere a la instancia real de some .

Este es el error con 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

Comentario más útil

Incluso si no se usa comúnmente, o al menos no se informa comúnmente, me gustaría corregir esta regresión.

Todos 10 comentarios

Este es un buen candidato para usar git bisect para establecer cuándo se cambió el comportamiento, lo que podría dar alguna pista sobre si el cambio fue intencional (una característica) o no (un error).

No debería ser tan difícil convertir el ejemplo @ PVince81 proporcionado en un pequeño script de prueba que se puede usar por git bisect run .

Si no sabes cómo usar git bisect , ¡esta es una excelente oportunidad para subir de nivel!

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

¡Oh, me encanta bisecar! Yo me encargaré de esto ...

Aquí vamos: 911c498dc14dc4034ba019526bf58f8b24d77da0 El espía pasa a través de las llamadas con new (# 1626)

¡Gracias por hacer eso, @ PVince81! Una solución podría querer inspeccionar también # 1265, ya que toca qué cambios son necesarios para admitir el espionaje del constructor.

Cuando no se crea un objeto con new , se llama a este método , que altera el contenido de thisValue y por extensión thisValues . Por el contrario, el método llamado cuando se usa new deja inalterado thisValue .

considerando que nuestro código solo tiene un uso de esto, estaría más bien tentado a ir por la ruta rápida y cambiar nuestra única prueba que desencadenó esto, ya que no tengo tiempo para entender los aspectos internos de Sinon y no me siento calificado para hacer cambios potencialmente importantes

Dado que no parece que mucha gente se haya quejado de este problema, tal vez la gente generalmente no prueba de esta manera y una solución no vale la pena (solo una observación, depende de los mantenedores para decidir)

Incluso si no se usa comúnmente, o al menos no se informa comúnmente, me gustaría corregir esta regresión.

Encontré el mismo problema, ¿hay algún plan para solucionarlo?

@ ivan-zakharchuk Si nadie se ofrece como voluntario, no hay planes, no. Si desea que se solucione, hay un siguiente paso natural que podría tomar ;-)

Este es el compromiso ofensivo: https://github.com/sinonjs/sinon/issues/1683#issuecomment -364794930

Solo para decir, he pasado mucho tiempo tratando de escribir una solución para esto, pero no he tenido éxito. Es una pesadilla de valores this . El problema principal parece ser que new ing la función provista aquí crea inherentemente un this , mientras que thisValues[0] (como se usa en la publicación original) se refiere al this creado por new en la propia prueba (es decir, el var some = new window.SomeClass(); ) - muy confuso, lo sé.

Básicamente, arreglar esto significa intentar tenerlo en ambos sentidos: llamar a new absolutamente significa un nuevo this , pero tenemos que llamarlo dos veces (es decir, uno en la prueba de OP y otro en proxy-invoke.js ) para satisfacer ES6. Por lo tanto, siempre terminará con dos this es. Lo único que se me ocurrió fue vincular las funciones de un this al otro, pero eso fue demasiado complicado incluso para esto y rompió algunas otras cosas.

Espero que lo anterior tenga sentido, no dude en corregirlo o solicitar una aclaración. Vea aquí para un repaso de lo que realmente hace la palabra clave new : TLDR crea un nuevo objeto y lo convierte en this , sea cual sea el contexto.

De todos modos, una cosa que noté fue que 911c498 (la confirmación que introdujo la regresión) no incluye una prueba que cubra el problema que aborda: el requisito de usar new con las clases de ES6. Esto probablemente se deba a que las opciones de linting para las pruebas no permiten la palabra clave class ya que solo sirven para ES5. Tengo un compromiso de agregar una prueba para que cualquier solución futura para el problema actual no elimine la solución en 911c498; puedo PR si hay interés.

¿Fue útil esta página
0 / 5 - 0 calificaciones