【问题标题】:How can I fake a global context to isolate tests?如何伪造全局上下文以隔离测试?
【发布时间】:2014-03-10 23:05:35
【问题描述】:

我的单元测试在 node.js 中运行(使用 mocha、chai 和 sinon)。我正在测试的代码是在浏览器中运行的。

一些代码全局定义事物,而其他代码期望有一个window 对象并将对象添加到window。 (具体来说,我使用 shim 来模拟 ES6 的 Promise 对象。)到目前为止,我已经通过添加 global.window = global; 来伪造窗口对象,这只能让我到目前为止。当我想为下一组测试拆除我的假环境时,问题就出现了。

我尝试在before()beforeEach() 函数中调用require(),并尝试在after()afterEach() 函数中手动删除创建的对象。每次都会发生两种情况之一。要么全局对象从一个测试 JS 文件持续到下一个测试 JS 文件,要么在所有测试中神秘地不存在全局对象。

我不确定这是否与 mocha 运行测试 JS 文件的方式或 require() 的工作方式有关,但我没有想法。以前肯定有人解决过这个问题吗?

【问题讨论】:

  • "我正在测试的代码是在浏览器中运行的" 那么为什么不在浏览器中运行呢?或者这是一个愚蠢的问题?
  • @RobG 能够跳过浏览器减轻了测试套件的负担。

标签: javascript node.js unit-testing mocha.js sinon


【解决方案1】:

您可以使用 Node 的 vm module 将“浏览器代码”与套件的其余部分隔离开来。对于您的情况,这可能就足够了。例如:

var vm = require("vm");

var window = {};
window.window = window;

vm.runInNewContext("foo = ['foo val'];", window);
console.log(window.foo);
console.log(window.window.foo);
console.log(window.window.foo === window.foo);
vm.runInNewContext("window.bar = ['bar val'];", window);
console.log(window.bar);
console.log(window.window.bar);
console.log(window.window.bar === window.bar);

contextify package 上的文档提到了vm 无法很好处理的用例(异步代码)。在这些情况下,您必须使用像 contextify 这样的工具,它可以完成 vm 的工作并支持异步代码。

如果您需要在模拟浏览器中通常存在的 API 的环境中运行您的浏览器代码,那么可以使用 jsdom,我已经成功地使用它来测试导航 DOM 树的代码。 Jsdom 恰好在内部使用 contextify 将浏览器代码与 Node 的其余部分隔离开来。

【讨论】:

    【解决方案2】:

    看看rewire

    它让你:

    • 为其他模块或全局变量(如进程)注入模拟
    • 泄露私有变量
    • 覆盖模块内的变量。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-05-17
      • 2018-12-02
      • 1970-01-01
      • 1970-01-01
      • 2019-06-09
      • 1970-01-01
      • 2019-06-26
      相关资源
      最近更新 更多