You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 21:10:28