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

如何使用Mocha测试返回匿名函数的Express授权中间件?

授权中间件单元测试实现方案

要测试你的授权中间件,核心是模拟Express中间件依赖的req、res、next对象,然后验证中间件的行为是否符合预期。下面是具体的测试步骤和代码示例:

测试核心逻辑

authorizeStrategy返回的是一个(req, res, next)格式的函数,测试时需要:

  • 构造包含USER.role的req对象,模拟当前登录用户的角色
  • 用Sinon Stub模拟res的status和json方法(支持链式调用)
  • 用Sinon Spy模拟next函数,验证是否被调用

完整测试代码

const sinon = require('sinon');
const authorizeMiddleware = require('../../middleware/authorize');

describe('Authorize Middleware Tests', function() {
  let req;
  let res;
  let next;

  beforeEach(function() {
    // 初始化基础模拟对象
    req = { USER: { id: 1, role: 'admin' } };
    // 模拟res对象,支持status().json()链式调用
    res = {
      status: sinon.stub().returnsThis(),
      json: sinon.stub()
    };
    // 用Spy监控next函数
    next = sinon.spy();
  });

  it('调用next当用户角色匹配时', function() {
    const authorize = authorizeMiddleware.authorizeStrategy('admin');
    authorize(req, res, next);
    
    // 验证next被调用,res的方法未触发
    sinon.assert.calledOnce(next);
    sinon.assert.notCalled(res.status);
    sinon.assert.notCalled(res.json);
  });

  it('返回403当用户角色不匹配时', function() {
    req.USER.role = 'user';
    const authorize = authorizeMiddleware.authorizeStrategy('admin');
    authorize(req, res, next);
    
    // 验证返回403和正确的错误消息
    sinon.assert.calledWith(res.status, 403);
    sinon.assert.calledWith(res.json, { message: 'Unauthorized' });
    // next未被调用
    sinon.assert.notCalled(next);
  });

  it('允许所有用户访问当未传入roles参数时', function() {
    const authorize = authorizeMiddleware.authorizeStrategy();
    authorize(req, res, next);
    
    sinon.assert.calledOnce(next);
    sinon.assert.notCalled(res.status);
  });

  it('调用next当用户角色在指定角色数组内时', function() {
    const authorize = authorizeMiddleware.authorizeStrategy(['admin', 'moderator']);
    authorize(req, res, next);
    
    sinon.assert.calledOnce(next);
  });

  it('返回403当用户角色不在指定角色数组内时', function() {
    req.USER.role = 'guest';
    const authorize = authorizeMiddleware.authorizeStrategy(['admin', 'moderator']);
    authorize(req, res, next);
    
    sinon.assert.calledWith(res.status, 403);
    sinon.assert.calledWith(res.json, { message: 'Unauthorized' });
    sinon.assert.notCalled(next);
  });
});

关键细节说明

  • 链式调用处理:res.status().json()是链式调用,所以用sinon.stub().returnsThis()让status方法返回res本身,确保链式调用能正常执行。
  • 独立测试:不需要依赖认证中间件的Stub,直接构造req.USER即可,避免测试耦合,让每个测试只关注授权逻辑本身。
  • Sinon断言:使用sinon.assert系列方法验证函数调用情况,比手动判断更精准可靠。

内容的提问来源于stack exchange,提问作者Mathieu Thauvoye

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 05:35:42