如何使用sinon和Mocha对NodeJS中mysql query的promisify调用进行mock
问题原因
你的实现存在两个核心错误直接导致stub不生效、调用超时:
withArgs({})参数匹配完全失效:业务代码中调用query时传入的参数是{ sql: sqlQuery, timeout: 1000, values: [value1, inputValue] },而非空对象,sinon stub匹配不到对应入参就不会执行你写的callsFake逻辑,默认返回undefined,导致promisify包装后的函数一直处于pending状态触发超时。- stub返回逻辑不符合
util.promisify的要求:mysql原生query是回调风格函数,最后一个入参是(error, result)格式的回调函数,promisify就是基于这个回调签名做的异步封装。你直接让stub返回Promise是无效的,promisify不会识别这个返回值,依旧会等待回调被调用。
正确实现代码
可以选择去掉严格的withArgs匹配,或者用sinon模糊匹配器校验入参,stub内部主动调用传入的回调返回结果:
query : sinon.stub().callsFake(function (queryOption, callback): void { const dummyArray = [{ userid: 'xyz' }]; // 第一个参数为错误对象,传null代表查询成功,第二个参数为查询结果 callback(null, dummyArray); }),
如果需要做参数校验,可以把withArgs改成匹配对应结构即可:
query : sinon.stub().withArgs(sinon.match({ sql: sqlQuery, // 替换为业务代码中实际的sqlQuery变量值 timeout: 1000, values: sinon.match.array })).callsFake(function (queryOption, callback): void { const dummyArray = [{ userid: 'xyz' }]; callback(null, dummyArray); }),
补充说明
修改后stub会完全符合mysql query的回调签名,promisify会自动把回调的返回值转为resolve的Promise,不会再出现超时挂起的问题。如果要模拟查询错误的场景,只需要把callback的第一个参数传入Error对象即可。
内容的提问来源于stack exchange,提问作者user4002112
相关产品推荐
相关产品推荐

