使用sinon.stub()存根异步处理器时遇undefined错误求助
问题解决思路
核心错误原因
你报错Trying to stub property 'authenticate' of undefined,本质是你的authenticateService不是类,而是直接导出的普通对象,但你用了sinon.stub(authenticateService.prototype, "authenticate")去存根——只有类的实例才会有prototype,普通对象根本没有这个属性,自然会报undefined错误。
具体修正步骤
1. 修正服务存根的写法
直接存根authenticateService导出的authenticate方法,不需要碰prototype:
// 测试里的beforeEach改成这样 beforeEach(() => { sinon.stub(authenticateService, "authenticate") .resolves(true); // 原服务返回的是布尔值isValid,而非{status:200} })
2. 修复handler里的语法错误
你的authenticateHandler.js有两个低级错误:
module.export.handler应该是module.exports.handler(少了个s)- 调用
authenticate(username, password)时,未从event.body中提取参数
修正后的handler:
const authenticateService = require('./authenticateService'); module.exports.handler = async (event) => { const { username, password } = event.body; try { const auth = await authenticateService.authenticate(username, password); if (auth) { // 业务逻辑代码 } return { statusCode: 200 }; // 注意是statusCode,若用statusCodes.OK需提前定义常量 } catch (err) { // 处理认证失败场景 return { statusCode: 401, body: err.message }; } }
3. 补全测试代码的缺失部分
你的测试未调用handler获取响应,也未定义response变量,补上后完整测试代码:
const { expect } = require('chai'); const sinon = require('sinon'); const authenticateService = require('./authenticateService'); const { handler } = require('./authenticateHandler'); describe(`Admin Module`, () => { beforeEach(() => { // 存根authenticate方法,返回true sinon.stub(authenticateService, "authenticate").resolves(true); }) afterEach(() => { // 恢复存根,避免影响其他测试用例 authenticateService.authenticate.restore(); }) describe(`test auth`, () => { it(`Receives POST event expects statusCode 200`, async () => { const event = { httpMethod: `POST`, resourcePath: `/admin/authentications`, body: { username: `fizz@email.com`, password: `buzz`, recaptchaToken: `some_token` }, }; // 调用handler获取响应 const response = await handler(event); expect(response.statusCode).to.equal(200); // 验证authenticate是否被正确调用 expect(authenticateService.authenticate.calledWith('fizz@email.com', 'buzz')).to.be.true; }) // 新增认证失败的测试用例 it(`Receives invalid credentials expects statusCode 401`, async () => { // 存根authenticate方法,让它抛出错误 authenticateService.authenticate.rejects(new Error('invalid_credentials')); const event = { httpMethod: `POST`, resourcePath: `/admin/authentications`, body: { username: 'wrong@email.com', password: 'wrongpass', recaptchaToken: 'some_token' } }; const response = await handler(event); expect(response.statusCode).to.equal(401); expect(response.body).to.equal('invalid_credentials'); }) }) })
额外注意点
- 原
authenticateService.js的导出写法有误,你写的module.exports = (() => { ... })未执行立即执行函数,应改成module.exports = (() => { ... })(),否则导出的是函数而非包含authenticate方法的对象。 - 存根异步方法时,用
resolves()或rejects()比callsFake(() => Promise.resolve(...))更简洁。
内容的提问来源于stack exchange,提问作者Echen
相关产品推荐
相关产品推荐

