使用Mocha、Sinon、Chai测试时,Promise未解析致断言失败问题
解决Mocha中Promise未等待导致Spy断言失败的问题
我完全懂你碰到的这个坑——你的测试代码没等fn.method()返回的Promise解析就跑去执行断言了,所以expect(test).to.have.been.called会在then回调触发前就跑完,自然断言失败,打印顺序也乱了套。
问题根源
Mocha默认不会自动等待异步操作(比如Promise)完成。你原来的代码里,fn.method().then(...)是异步执行的,但测试函数会同步走完所有代码:先调用fn.method(),然后立刻执行console.log("goodbye")和expect(test)...,这时候then里的test()还没机会执行,spy自然没被调用。
解决方案:让Mocha等待Promise完成
有两种常用的方式可以解决这个问题,都能保证断言在then回调执行后才运行,同时让打印顺序符合你的预期。
1. 返回Promise给Mocha
Mocha会自动识别测试函数返回的Promise,并等待它resolve后再结束测试。把你的断言放到Promise链的后续then里,就能确保顺序正确:
const sinon = require('sinon'); const { expect } = require('chai'); describe('异步方法测试', () => { it('应正确调用test spy并按预期顺序打印', () => { let test = sinon.spy(); let fn = { method: sinon.stub().resolves("hello") }; // 返回Promise链,让Mocha等待所有异步操作完成 return fn.method().then(response => { console.log(response); // 先打印"hello" test(); }).then(() => { console.log("goodbye"); // 再打印"goodbye" // 现在断言才会在test被调用后执行 expect(fn.method).to.have.been.called; expect(test).to.have.been.called; }); }); });
2. 使用async/await(更简洁的写法)
现代JS里用async/await处理异步会更直观,Mocha完全支持async测试函数,它会自动等待await后的Promise完成:
const sinon = require('sinon'); const { expect } = require('chai'); describe('异步方法测试', () => { it('应正确调用test spy并按预期顺序打印', async () => { let test = sinon.spy(); let fn = { method: sinon.stub().resolves("hello") }; // 等待Promise解析 const response = await fn.method(); console.log(response); // 先打印"hello" test(); console.log("goodbye"); // 再打印"goodbye" // 此时test已经被调用,断言会通过 expect(fn.method).to.have.been.called; expect(test).to.have.been.called; }); });
效果验证
修改后,测试会先等待fn.method()的Promise resolve,执行then回调里的console.log("hello")和test(),之后再打印"goodbye"并执行断言,完全符合你的预期,expect(test).to.have.been.called也会顺利通过。
内容的提问来源于stack exchange,提问作者cowboybebop
相关产品推荐
相关产品推荐

