// CODE var catalogDOM = (function() { return { updateAvailabilityForItem: function(quant) { console.log(">>>> in updateAvailabilityForItem") }, syncAvailability: function() { return new Promise(function(resolve, reject) { ... }) } } })(); $(document).on("click", ".item_info", function() { console.log(">> calling sync") catalogDOM.syncAvailability() .catch(function() { console.log(">>> caught") catalogDOM.updateAvailabilityForItem(0) }) }) // SPEC describe("click on item_info", function() { beforeEach(function() { info_btn = affix(".item_info") spyOn(catalogDOM, "updateAvailabilityForItem") syncFunction = spyOn(catalogDOM, "syncAvailability") syncFunction.and.returnValue(new Promise(function(resolve, reject) {reject()})) info_btn.click() }) it("should call updateAvailabiliytForItem", function() { expect(catalogDOM.updateAvailabilityForItem).toHaveBeenCalledWith(0) }) }) // CONSOLE OUTPUT >> calling sync >>> caught >>>> in updateAvailabilityForItem La especificación anterior está fallando, además, puedo ver a través de la consola, ver los mensajes anteriores, que catalogDOM.updateAvailabilityForItem en realidad se está llamando... ¿hay algo en la configuración de la promesa que niega el espía?
El problema es que la promesa está ocurriendo de forma asíncrona (en un momento posterior) y cuando se espera, es demasiado pronto.
Para un desbloqueo rápido, puede envolver su expectativa en un setTimeout que reducirá la prioridad de lo que sucede en setTimeout después de la promesa, pero no estoy seguro de si este es un buen enfoque.
// add done to function argument it("should call updateAvailabiliytForItem", function(done) { setTimeout(() => { expect(catalogDOM.updateAvailabilityForItem).toHaveBeenCalledWith(0); // call done to let Jasmine know your asynchronous work is done. done(); }, 100); })Puede leer más sobre cómo probar cosas asincrónicas en Jasmine aquí: https://jasmine.github.io/tutorials/async
Usualmente uso async/await para tareas asincrónicas.