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

使用Chai测试TypeScript错误抛出时遭遇测试失败问题

解决Chai测试无法捕获Express中间件抛出错误的问题

我之前也碰到过一模一样的情况——明明代码里已经抛出了指定错误,但Chai测试就是检测不到。大概率是Express的错误处理逻辑和测试里的异步代码处理没配合好,咱们一步步捋清楚问题:

先理清楚你的核心代码问题

先把你截断的users.ts补全并标注关键细节:

// users.ts
const database = require('../databases/postgres');

module.exports = {
  create: async (req, res, next) => {
    try {
      if (!req.body.email) {
        throw new Error('email needed');
      }
      // 注意:这里的user变量未定义,应该是req.body?
      const userCreated = await database.createUser(req.body); 
      userCreated ? res.status(200).send('success') : res.status(400).send('failed');
    } catch (err) {
      // 重点!必须调用next(err)把错误传给Express的错误处理链
      next(err); 
    }
  }
};

问题根源分析

  1. Express异步中间件的错误传递:如果在catch块里不调用next(err),Express会悄悄吞掉这个错误,测试根本拿不到错误信息。
  2. Chai异步测试的处理方式:测试异步代码时,要么用done()回调,要么用async/await,否则测试会提前结束,误以为没有错误抛出。
  3. 缺少自定义错误处理中间件:Express默认的错误处理不会把错误信息返回给客户端,测试自然捕获不到指定的错误文本。

正确的Chai测试写法(以chai-http为例)

假设你的测试文件是users.test.js,按照下面的方式编写测试:

const chai = require('chai');
const chaiHttp = require('chai-http');
const app = require('../app'); // 你的Express实例
const expect = chai.expect;

chai.use(chaiHttp);

describe('User Creation API', () => {
  // 用done()回调的写法
  it('should return "email needed" error when email is missing', (done) => {
    chai.request(app)
      .post('/users') // 对应你的create路由
      .send({}) // 不传email参数
      .end((err, res) => {
        expect(res).to.have.status(400); // 匹配你自定义的错误状态码
        expect(res.text).to.equal('email needed'); // 匹配抛出的错误信息
        done(); // 必须调用done结束异步测试
      });
  });

  // 更简洁的async/await写法
  it('should throw "email needed" error when email is missing (async/await)', async () => {
    try {
      const res = await chai.request(app).post('/users').send({});
      // 如果走到这一步,说明没抛出预期错误,直接断言失败
      expect.fail('Expected an error but none was thrown');
    } catch (err) {
      expect(err.response).to.have.status(400);
      expect(err.response.text).to.equal('email needed');
    }
  });
});

别忘了加Express错误处理中间件

在你的app.js里必须添加自定义错误处理中间件,把错误信息返回给客户端:

// app.js
// ...其他路由配置...

// 错误处理中间件(必须放在所有路由之后)
app.use((err, req, res, next) => {
  console.error(err.stack);
  // 这里返回你需要的状态码和错误信息
  res.status(400).send(err.message);
});

最后再检查两个细节

  • 确认你的create中间件里的catch块确实调用了next(err),否则错误无法传递到处理链。
  • 检查代码里的变量是否正确:比如你原来的database.createUser(user)里的user是否是req.body,未定义的变量会抛出其他错误,干扰测试结果。

内容的提问来源于stack exchange,提问作者Langlois.dev

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 06:38:43