Espero que alguien pueda ayudarme a comprender la interactividad de los prototipos js y jest.spOn() .
Tengo un pequeño ejemplo: una clase de ejemplo en el archivo TestObj.ts :
export default class TestObj { foo() { // Do Something eg console.log("Hello World!"); } } El siguiente caso de prueba de ejemplo tiene éxito, pero el console.log nunca se ejecuta.
import TestObj from './TestObj'; const spyObj = jest.spyOn(TestObj.prototype, 'foo'); test('debug test', () => { const obj = new TestObj(); obj.foo(); expect(spyObj).toHaveBeenCalled(); }); Si cambio el caso de prueba de ejemplo a lo siguiente, la prueba tiene éxito y la instrucción console.log se llama como se esperaba.
import TestObj from './TestObj'; test('debug test', () => { const spyObj = jest.spyOn(TestObj.prototype, 'foo'); const obj = new TestObj(); obj.foo(); expect(spyObj).toHaveBeenCalled(); });¿Alguna idea de por qué la versión que usa la variable spyOn global no funciona como se esperaba?
Parece no estar relacionado con los prototipos. El mismo Problema está ahí para una función sin ningún tipo de clase, editando el fragmento del Primer Código ( TestObj.ts ) a esto:
export foo() { // Do Something eg console.log("Hello World!"); };Recibimos el mismo problema para el segundo recorte actualizado. (La prueba tiene éxito, pero nunca se alcanza el registro de la consola).
import * as testlib from './TestObj'; const spyObj = jest.spyOn(testlib, 'foo'); test('debug test', () => { testlib.foo(); expect(spyObj).toHaveBeenCalled(); });Sin embargo, si actualizamos el segundo fragmento a lo siguiente, la prueba tiene éxito y se ejecuta el registro de la consola:
import * as testlib from './TestObj'; const spyObj: jest.SpyInstance; beforeEach(() => { spyObj = jest.spyOn(testlib, 'foo'); }); test('debug test', () => { testlib.foo(); expect(spyObj).toHaveBeenCalled(); });Sin embargo, todavía no tengo idea de por qué descubro este problema.
quien alguna vez se encuentra con esta publicación,
Investigué mucho más (prueba y error, mdn, página de manual de broma y muchos artículos medianos) y creo que descubrí el motivo del comportamiento extraño. Para entender este tema es importante conocer una serie de puntos:
jest.SpyOn(TestObj.prototype, 'foo'); en realidad se implementa como: TestObj.prototype.foo = new jest.fn().mockImplementation(()=>{original_TestObj.prototype.foo()}); Esto significa que espiar una función de un prototipo de clase en realidad está cambiando una variable global.spyOn parece ser la misma que para jest.fn() , una implementación vacía, lo que significa que aún se puede llamar a la maqueta pero no se ejecuta ningún código, especialmente la implementación original. test('should foo', () => { const testObj = new TestObj(); const spyOnFn = jest.spyOn(testObj, 'foo'); // Do anything expect(spyOnFn).to//Have been anything });spyOn de la misma función en más de una prueba, intente crear una variable global para la prueba, pero use antes de cada funcionalidad de broma para configurar el espía. Esta funcionalidad se ejecuta después del reinicio de todos los simulacros (si está habilitado). p.ej: let spyOnFunction1: jest.SpyInstance; beforeEach(()=> { spyOnFunction1 = jest.spyOn(TestObj.prototype, 'foo'); });