应用导出为Promise时启动mocha chai测试报.then is not a function如何解决
问题原因
- 核心原因:
server/app.js使用ES Module规范的export default导出Promise对象,而测试文件test/test.js用CommonJS规范的require语法导入。CommonJS导入ES Module的默认导出时,不会自动提取default值,你拿到的实际是一个包含default属性的对象,即app = { default: appPromise },所以直接调用app.then自然会报“then不是函数”的错误。 - 附加可能原因:
@babel/register配置加载时机/配置不正确,你写的require('@babel/core').transform('code', {})是无效代码没有实际作用,没有给babel传入正确的转译规则,导致ES6导出语法没被正确转成CommonJS兼容的格式,进一步放大了导出导入的不兼容问题。
解决方案
方案1:调整导入逻辑取default属性
直接在require后取default属性即可,修改test/test.js的导入代码:
// 原来的导入 // const app = require('../server/app') // 修改为 const app = require('../server/app').default;
方案2:统一模块规范
把所有模块都改成CommonJS规范,修改server/app.js的导出代码:
// 原来的导出 // export default appPromise; // 修改为 module.exports = appPromise;
不需要改导入代码,直接用原来的const app = require('../server/app')即可正常调用then。
方案3:修复babel配置正确转译ES Module
首先删除test/index.js里无效的require('@babel/core').transform('code', {})代码,给@babel/register配置正确的转译规则,确保ES Module的默认导出被自动转成CommonJS的导出:
- 安装依赖:
npm install @babel/preset-env --save-dev - 项目根目录新增
.babelrc配置文件:
{ "presets": ["@babel/preset-env"] }
- 修改
test/index.js的配置:
require('@babel/register')({ extensions: ['.js'], presets: ['@babel/preset-env'] }); let tests = require('./tests.js'); module.exports = {tests};
转译生效后ES Module的export default会被自动处理为CommonJS的导出,不需要额外取default属性。
补充注意:大部分测试框架(比如Mocha)不支持在
describe块外层异步定义测试用例,解决导出问题后建议把异步初始化逻辑放到全局before钩子中,示例代码如下:const appPromise = require('../server/app').default; let request; before(async () => { const app = await appPromise; request = chai.request(app).keepOpen(); }); describe('测试用例组', () => { it('测试接口', async () => { const res = await request.get('/test'); res.status.should.equal(200); }) })
内容的提问来源于stack exchange,提问作者shogitai
相关产品推荐
相关产品推荐

