Node.js中使用Mocha从testHook导出变量出现undefined问题
解决Mocha中从testHook导出变量为undefined的问题
这个问题我之前也碰到过,核心是模块加载时机和基本类型值传递的双重问题,咱们一步步拆解原因和解决方案:
问题根源
- 模块加载早于钩子执行:当测试文件执行
var xyz = require("testHook").xyz;时,这是Mocha加载测试文件的第一时间就完成的,此时testHook里的beforeEach钩子还没运行,abc()也没被调用,所以exports.xyz还是undefined,这个值被直接赋值给了测试文件里的变量xyz。 - 基本类型是值拷贝:后续
beforeEach运行时,虽然abc()把exports.xyz改成了10,但测试文件里的xyz变量是之前拷贝的undefined——因为数字是基本类型,赋值是值传递,不是引用,所以后续修改exports.xyz不会影响已经赋值的变量。 - 另外你testHook里的
console.log(this.xyz)输出10其实是个巧合:Mocha钩子中的this指向的是测试上下文对象,不是模块的exports,这里输出10可能是Mocha上下文刚好有同名属性,和你给exports赋值的逻辑无关,建议改成console.log(exports.xyz)来准确查看模块导出的变量值。
解决方案
下面给你两种靠谱的解决方式,按需选择:
方案1:导出引用类型(推荐)
用一个对象来存储变量,因为对象是引用类型,测试文件拿到的是对象的引用,后续修改对象属性会同步更新:
修改testHook.js:
// 用模块级对象存储变量,保证引用一致性 const sharedData = {}; function abc() { // 修改对象的属性,而不是直接给exports赋值 sharedData.xyz = 10; } beforeEach(() => { abc(); console.log(sharedData.xyz); // 正确输出10 }); // 导出这个共享对象 exports.sharedData = sharedData;
测试文件修改为:
// 获取共享对象的引用 const { sharedData } = require("testHook"); class test1 { execute() { describe("test suite 1", async () => { it("test 1", async () => { // 动态读取对象的最新属性值 console.log(sharedData.xyz); // 现在会输出10 }); }); } } new test1().execute();
方案2:导出获取函数
如果不想用对象,也可以导出一个函数,每次调用时动态获取最新的变量值:
修改testHook.js:
// 用模块级变量存储值 let xyz; function abc() { xyz = 10; } beforeEach(() => { abc(); console.log(xyz); // 输出10 }); // 导出获取函数,每次调用返回最新的xyz值 exports.getXyz = () => xyz;
测试文件修改为:
// 获取获取函数 const { getXyz } = require("testHook"); class test1 { execute() { describe("test suite 1", async () => { it("test 1", async () => { // 调用函数获取最新值 console.log(getXyz()); // 输出10 }); }); } } new test1().execute();
这两种方式都能解决你遇到的问题,核心思路就是避免直接赋值基本类型,而是通过引用或者函数调用动态获取最新值。
内容的提问来源于stack exchange,提问作者user522170
相关产品推荐
相关产品推荐

