如何使用Mocha、Sinon stub对NPM Request库进行单元测试?
问题根因
- 你Stub的是
request.get方法,但业务代码里调用的是顶层request()方法,Sinon的Stub没匹配到对应的调用,请求还是走了真实的网络逻辑,自然会抛出域名解析失败的Error: getaddrinfo ENOTFOUND报错。 - 你的
apiFunction没有返回Promise,测试代码里直接调用apiFunction.then会直接抛出异常,也没法等待异步回调执行完成。 - 断言使用了
assert.equal对比对象,该方法只会做引用相等判断,即使内容一致也会断言失败;同时Stub返回的是JSON序列化后的字符串,直接和对象对比也会不匹配。
修复后的代码示例
调整测试用例逻辑
describe(`api tests`, () => { it(`should return expected data`, async () => { // 直接stub顶层request方法,匹配业务代码的调用方式 const requestStub = sinon.stub(request).yields(null, null, JSON.stringify({test: `stubtest`})) const res = await apiFunction() // 对比对象要使用deepEqual,先把返回的JSON字符串反序列化 assert.deepEqual(JSON.parse(res), {test: "stubtest"}) // 可选:验证Stub确实被正常调用 assert.isTrue(requestStub.calledOnce) // 测试结束后恢复被Stub的方法,避免影响其他用例 requestStub.restore() }) })
改造apiFunction返回Promise
const apiFunction = () => { return new Promise((resolve, reject) => { request( { url: `http://url` }, (err, response, body) => { if (err) return reject(err) console.log(body) // 输出 {"test":"stubtest"} resolve(body) }) }) }
额外注意点
- 如果业务代码里确实是用
request.get发送请求,也可以保持Stubrequest.get,但要确保调用时用的是request.get()而不是顶层request() - 如果你不想手动处理Promise,也可以使用Sinon的
resolves/rejects方法配合Promise化的请求库使用,代码会更简洁
内容的提问来源于stack exchange,提问作者succeed
相关产品推荐
相关产品推荐

