Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

183
Vistas
¿Cómo asegurarse de que NO se haya realizado una devolución de llamada?

Digamos que tengo la siguiente función que verifica periódicamente una condición hasta que se cumple.

 let loopWithSleep = (callback) => { if (conds.every(cond => { return cond; })) { console.log("wooho"); callback(); } else { console.log("waiting..."); setTimeout(loopWithSleep, 500, callback); } };

Y supongamos que tengo un conjunto de pruebas que se parece a esto:

 describe('Callback', () => { it('should NOT use the provided callback', (done) => { var conds = [true, false]; loopWithSleep(done); }); });

¿Cómo puedo probar si una función de devolución de llamada (en el ejemplo anterior llamada done ) no ha sido llamada y aún así pasa la prueba?

El ejemplo anterior da como resultado un error: Error: timeout of 2000ms exceeded. Ensure the done() callback is being called in this test.

Estaba tratando de envolver la prueba en chai.assert.throws( ... ); pero sin éxito.

about 4 years ago · Santiago Trujillo
2 Respuestas
Responde la pregunta

0

En primer lugar, el diseño de la función podría mejorar. Se basa en la variable global cond , que es frágil; si cond cambia de nombre en otra parte del código, la función se interrumpe. Todos los datos deben pasarse como parámetros. Esto ayuda a aislar componentes y mitigar errores y facilita las pruebas.

Sugeriría una reescritura inicial como:

 const callWhenConditionsMet = (callback, conds, ms=500) => { if (conds.every(Boolean)) { callback(); } else { setTimeout(callWhenConditionsMet, ms, callback, conds, ms); } };

Esto todavía parece subóptimo debido a la falta de promesas o argumentos, sin mencionar el uso de encuestas cuando un enfoque basado en eventos probablemente sea más apropiado (un posible problema XY ), pero asumiré que es lo suficientemente bueno para su caso de uso.

En cuanto a la prueba, puede estar confundiendo done() con un simulacro/espía. done() no es apropiado para aserciones; solo está ahí para indicarle a Mocha que la prueba finalizó cuando se trata de devoluciones de llamada asincrónicas. Es esencialmente un atajo a la promisificación. Tener que usar done en exceso puede indicar un diseño deficiente en su biblioteca o conjunto de pruebas (o ambos). Prefiere las promesas.

En lugar de done , simule la devolución de llamada con su biblioteca favorita, como Sinon, pase el simulacro a la función que está probando, avance el tiempo según sea necesario y luego afirme que se llamó (o no) al simulacro.

Además, utilice temporizadores falsos para evitar que sus pruebas tomen mucho tiempo y para garantizar la confiabilidad. Si está utilizando temporizadores falsos, ¡no es necesario que lo done en absoluto! (otro problema XY)

 const {assert} = require("chai"); const sinon = require("sinon"); const callWhenConditionsMet = (callback, conds, ms=500) => { if (conds.every(Boolean)) { callback(); } else { setTimeout(callWhenConditionsMet, ms, callback, conds, ms); } }; describe("callWhenConditionsMet", () => { let clock; let spy; beforeEach(() => { clock = sinon.useFakeTimers({toFake: ["setTimeout"]}); spy = sinon.spy(); }); afterEach(() => { clock.restore(); spy = null; }); it("should invoke the callback right away when all conditions are true", () => { callWhenConditionsMet(spy, [true, true]); assert.isTrue(spy.called); }); it("should not invoke the callback when a condition is false", () => { callWhenConditionsMet(spy, [true, false]); clock.tick(2000); assert.isFalse(spy.called); }); it("should not initially call when false, but then call later when true", () => { const conds = [false, true]; callWhenConditionsMet(spy, conds, 1000); clock.tick(5000); assert.isFalse(spy.called); conds[0] = true; clock.tick(2000); assert.isTrue(spy.called); }); });
about 4 years ago · Santiago Trujillo Denunciar

0

Si bien la respuesta proporcionada por @ggorlen es ciertamente útil, creo que está demasiado diseñada.

A continuación se muestra mi respuesta inspirada en su comentario a la pregunta. Utiliza Mocha y chai con el complemento chai-spies .

 describe("callWhenConditionsMet", () => { beforeEach(() => { conds = [true, false]; }); it('should eventually use the callback function', async function () { const mock = chai.spy(); loopWithSleep(mock); await new Promise(function(resolve) { setTimeout( function() {resolve(); }, 500);}); chai.expect( mock ).not.to.have.been.called(); conds[1]=true; await new Promise(function(resolve) { setTimeout( function() {resolve(); }, 500);}); chai.expect( mock ).to.have.been.called(); }); });
about 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda