Así que tengo una clase muy simple que hace lo siguiente:
cleanup para eliminar el controlador a pedido export default class TestClass { constructor() { this.element = document.getElementById("test"); this.element.addEventListener("click", this.clickHandler); } clickHandler(e) { console.log("Click handler called"); } cleanup() { this.element.removeEventListener("click", this.clickHandler); } }Y tengo una prueba en la que apago el controlador (necesito cambiar su comportamiento) y hago algunas comprobaciones.
describe("Test", function () { beforeEach(function () { this.instance = new TestClass(); this.clickHandlerStub = sinon.stub(this.instance, "clickHandler"); }); afterEach(function () { this.instance.cleanup(); delete this.instance; }); it("test case", function () { document.getElementById("test").click(); expect(this.clickHandlerStub.calledOnce).to.equal(true); }); }); El comportamiento esperado es stub (anular) el controlador (por lo que no debería aparecer ningún registro) y mi expectativa debería pasar ya que debería llamarse una vez cuando se hace clic en el elemento. Sin embargo, parece que sigue registrando y la expectativa falla.
Si cambio la forma en que vinculo el controlador de eventos y uso una función de flecha, todo funciona bien.
this.element.addEventListener("click", () => this.clickHandler()); Pero entonces no puedo eliminar el controlador de eventos en mi método de cleanup , ya que addEventListener y removeEventListener necesitan pasar la misma referencia del controlador para que funcionen correctamente.
Creé un ejemplo reproducible en codesandbox en caso de que sea útil.
Entonces, ¿qué me estoy perdiendo aquí?
Puede stub prototipo de TestClass .
this.clickHandlerStub = sinon .stub(TestClass.prototype, "clickHandler") .callsFake(() => { console.log(`Now it's calling the fake handler`); });La limpieza seria
this.clickHandlerStub.restore();https://codesandbox.io/s/mocha-unit-test-example-forked-sstfz?file=/src/index.js
Referencias:
Por cierto, prefiero no usar this en un contexto global. En cambio, los crearía como variables let .
describe('...', () => { let clickHandlerStub; beforeEach(() => { clickHandlerStub = ... }); afterEach(() => { clickHandlerStub.restore(); }); });