如何伪造全局上下文来隔离测试?

时间:2014-03-10 23:05:35

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

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

有些代码在全局范围内定义,而其他代码则希望有window个对象,并将对象添加到window。 (具体来说,我正在使用垫片来模拟ES6的Promise对象。)到目前为止,我通过添加global.window = global;伪造了窗口对象,这只能让我到目前为止。当我想拆掉我的假环境进行下一组测试时,就会出现问题。

我尝试在require()before()函数中进行beforeEach()次调用,我尝试手动删除after()或{{1}中创建的对象}} 功能。每次都会发生两件事之一。全局对象从一个测试JS文件持久存储到下一个测试JS文件或全局对象在所有测试中神秘地缺失。

我不确定这是否与mocha运行测试JS文件或afterEach()如何工作的方式有关,但我没有想法。当然有人之前已经解决了这个问题吗?

2 个答案:

答案 0 :(得分:1)

您可以使用节点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的其余部分隔离开来。

答案 1 :(得分:1)

查看rewire

它可以让你:

  • 为其他模块注入模拟,或者为进程
  • 注入全局数据
  • 泄漏私人变量
  • 覆盖模块中的变量。