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

如何在CommonJS中动态导入ESModule版本的chai?

问题

Chai 5.1.2已转为ESModule,能否在CommonJS文件中继续使用?项目中仅将Chai作为单元测试的开发依赖,不想升级项目模块为ESModule。

尝试过以下几种方式,但都存在问题:

  1. 直接封装返回Promise的expect函数,报错无法链式调用:
const expect = (...args) => import('chai').then((mod) => mod.expect(...args));
expect ('true').to.equal('false');

报错信息:

TypeError: Cannot read properties of undefined (reading 'equal')

原因是该expect返回的是Promise,不是Chai的断言对象,无法直接链式调用.to.equal。

  1. 将测试代码包裹在import的回调中,可行但改动量大:
import('chai').then(chai => {
  expect = chai.expect;
  expect('true').to.equal('false');
});

需要把所有测试代码都放入回调,项目中大量expect语句,这种方式修改成本太高。

  1. 为每种断言类型封装单独函数,扩展性差:
const expectEqual = (arg1, arg2) => import('chai').then((mod) => mod.expect(arg1).to.equal(arg2));

要覆盖所有断言方法(如expect.to.be、expect.to.deep.equal等)需要编写大量重复函数,不现实。

更优解决方案

方案1:用require直接加载(Node.js >=14.13.0)

Node.js 14.13.0及以上版本支持在CommonJS中通过require加载ESModule,只需在末尾加上.default即可获取默认导出:

const chai = require('chai').default;
const expect = chai.expect;

// 原有测试代码无需改动,直接使用expect
expect('true').to.equal('false');

这是最简便的方案,完全兼容原有测试逻辑,不需要额外修改。

方案2:使用顶层await(Node.js >=14.8.0)

如果你的Node.js版本支持顶层await(CommonJS文件需确保后缀为.cjs,且版本符合要求),可以在文件顶部一次性完成异步导入:

const chai = await import('chai');
const expect = chai.expect;

// 后续所有测试代码正常使用expect,无需包裹
expect('true').to.equal('false');

这种方式也不需要修改原有测试代码,仅需在文件开头添加导入语句。

方案3:异步转同步(需额外依赖)

如果无法升级Node.js版本,可以使用deasync模块将异步导入转为同步(先执行npm install deasync --save-dev安装依赖):

const deasync = require('deasync');

let chaiInstance;
import('chai').then(mod => {
  chaiInstance = mod;
});

// 等待异步导入完成
deasync.loopWhile(() => !chaiInstance);

const expect = chaiInstance.expect;

// 正常使用断言
expect('true').to.equal('false');

这种方式需要额外安装依赖,优先推荐前两种方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 22:12:46