用Chai和Mocha测试socket.io的addBooking错误抛出时遇AssertionError如何解决?
嘿,我来帮你搞定这个测试问题!
首先得搞清楚你为啥会遇到这个错误:should.throw()是用来测试同步函数抛出的错误的,但addBooking返回的是一个Promise——当数据库插入失败时,它会通过reject返回错误,而不是同步抛出throw。你直接把一个pending状态的Promise传给should.throw(),它自然会报错说“预期是个函数,结果拿到了Promise对象”。
下面给你两种正确的测试方案,按需选择:
方案一:用Chai-as-promised插件(推荐,写法更简洁)
这个插件专门用来简化Promise的断言,能让你的测试代码更直观。
- 先安装插件:
npm install chai-as-promised --save-dev
- 在测试文件里启用它:
const chai = require('chai'); const chaiAsPromised = require('chai-as-promised'); chai.use(chaiAsPromised); const should = chai.should();
- 测试
addBooking的reject场景:
// 用Promise链式调用写法 it('应该在数据库插入失败时reject错误', () => { // 这里要传入会触发插入失败的测试数据,或者提前mock数据库方法让它返回错误 return addBooking(/* 错误测试数据 */) .should.be.rejectedWith('数据库插入失败'); // 这里填你预期的错误信息或Error类型 }); // 或者用async/await写法(更符合现代JS习惯) it('应该在数据库插入失败时reject错误', async () => { await addBooking(/* 错误测试数据 */) .should.be.rejectedWith(Error); // 也可以直接断言错误类型 });
方案二:不用插件,手动处理Promise的catch回调
如果不想额外装插件,也可以直接用Promise的catch结合Chai断言,再配合Mocha的done回调:
it('应该在数据库插入失败时reject错误', (done) => { addBooking(/* 错误测试数据 */) .catch((err) => { // 在这里写你的断言 err.should.exist; err.message.should.equal('数据库插入失败'); done(); // 告诉Mocha测试完成 }) .catch(done); // 捕获断言本身的错误,确保测试失败时能正确上报 });
额外提示:如果要测试socket.io的request事件逻辑
如果你还要测试socket.io的request事件监听代码(比如触发事件后是否正确处理了addBooking的错误),可以用Sinon来mock socket实例,比如:
const sinon = require('sinon'); it('当addBooking失败时,socket应该正确返回错误', (done) => { // mock一个socket对象,监听emit方法 const socket = { on: sinon.stub(), emit: sinon.stub() }; // 假设你的request事件处理逻辑是这样的,先绑定事件 socket.on('request', (data, callback) => { addBooking(data) .then(result => callback(null, result)) .catch(err => callback(err)); }); // 触发request事件,传入会导致失败的数据 socket.emit('request', /* 错误测试数据 */, (err) => { err.should.exist; err.message.should.equal('数据库插入失败'); done(); }); });
核心思路就是:同步错误用should.throw(),Promise的reject要用异步断言方式,别把两者搞混啦!
内容的提问来源于stack exchange,提问作者Dev
相关产品推荐
相关产品推荐

