如何在mocha测试中使用Node.js全局变量

14

我在使用Node.js时遇到了有关mocha测试全局对象的问题。

在索引文件中,我设置了全局变量的值。

// index.js
global.enums = enumTemp

export default app

然后在另一个文件中使用它。

// other.js

status = global.enums.object.status

这是一个REST API,并且如果我向服务器发出请求,它运行得很好。但是,当我使用Mocha测试时,似乎无法获取Node.js全局变量的值。有什么建议吗?


1
变量必须是全局的原因是什么?全局变量很丑陋,因为它们会引起各种问题。您应该考虑将变量放在自己的模块中,并在需要时进行引用。 - Tobi Kremer
我使用这个变量从数据库获取数据,当我启动服务器后,然后在另一个文件中使用全局变量。 - Toan Tran
你什么时候把变量设置为全局的?如果涉及到数据库,那对我来说就像是一个异步任务。在使用它之前,你应该等待值可用:要做到这一点,要么从获取值的文件中导出一个 promise,要么从需要值的位置获取值。顺便说一下,我赞同 @TobiKremer 的看法,即全局变量不是最好的选择。 - MarcoL
1
我已经使用了 Promise 来确保手头有来自数据库的数据。问题在于如何在 Mocha 中使用全局变量。我已经找到了适合我的解决方案。无论如何,感谢大家的关心。 :) - Toan Tran
3个回答

22

我通过使用Mocha hooks来为测试设置全局变量找到了适合自己的解决方案:

我通过使用Mocha钩子函数为测试设置全局变量找到了适合我的解决方案:

// setup.test.js
import MyFunc from '../helpers/my-func'

before((done) => {
  MyFunc.then((variable) => {
    global.variable = variable
    done()
  })
})

我们可以在测试中像在真正的代码中一样使用global.variable


1
“helpers/my-func.js”里面具体有什么内容?我看到它加载了一些 Promise,但我不确定为什么要这样做。 - haz

1
在Node中,只需使用global对象设置一个全局变量即可。
import {describe, test} from "mocha";

describe("suite", function () {
  test('test', function () {
    // given
    global.myVariable = myVariable;

    // when
    
  });
});

0

你应该摆脱全局变量,因为它们很丑陋,这可能也会解决你的问题。

关于 Node.js 的 require() 方法,有一个不太为人知的事实:模块在第一次 require 时被缓存。这使得可以运行昂贵的计算(或从数据库中获取某些内容),并在后续使用模块时进行缓存。

请观察此示例:

randomnumber.js

const calculateRandomNumber = limit => {
  console.log('calculateRandomNumber called');
  return parseInt(Math.random() * limit);
};

module.exports = calculateRandomNumber(1000);

other.js

module.exports = require('./randomnumber');

test.js

const randomnumber = require('./randomnumber');
const other = require('./other');
console.log(randomnumber);
console.log(other);

这将会输出相同的随机数两次,并且 calculateRandomNumber 只被调用一次,即使 randomnumber 模块在不同的地方被引用了。

30
全局变量在合适的情况下是有价值的。"你应该摆脱它们"并没有建设性。 - Petercopter
可能有一些情况下全局变量会有所帮助(例如将globals.Promise设置为不同的Promise库)。但在我看来,大多数情况下你可以并且应该摆脱它们,因为状态或操作潜在地远离代码,这使得跟踪和推理变得更加困难。 - Tobi Kremer
我不知道你是否解决了Toan Troan的问题,但你肯定解决了我的问题。我以前从未想过测试模块执行的次数,也不知道为什么。谢谢你,伙计。 - Héctor J. Vásquez
没有什么难的,只要理性思考,在测试运行时设置全局值就是测试所期望的全局值。从命令行到测试只需要一个步骤。 - worc
1
如果你的代码足够复杂(或者可能会变得足够复杂)以至于你需要编写测试,那么全局变量可能会对你造成伤害,而尽可能地消除它们是一个好主意。然而,这并不总是可能的,特别是如果你有一个庞大的遗留代码库。“你应该摆脱它们”并不是一种建设性的做法,不是因为它们有价值,而是因为有时它们是不可避免的。 - jameslafferty
1
没有冒犯的意思,但我们真的在讨论全局变量是否被认为是不良实践吗?我已经说过,如果可能的话(就像在OP的例子中),你应该摆脱它们。我甚至举了一个例子,说明它们可能有用,所以你只是重申了我已经说过的话。在全局变量中保存的状态会从代码的各个部分进行修改,与本地作用域变量相比,这使得难以知道发生了什么。如果你需要共享状态,并且总是使用全局变量,那么你将来会遇到困难。 - Tobi Kremer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接