要求并覆盖模块范围的变量以进行测试

时间:2018-03-25 17:28:12

标签: node.js unit-testing

我有一个这样的模块:

var hello = 'Hello Sir'

console.log(hello)

我想在另一个文件中要求模块rewire,但是当我这样做时会执行hello world。有没有办法在模块执行之前重新连接模块?

babel-plugin-rewire尝试

var g = require('./global.js')
g.__Rewire__('hello', 'Hello Madam')

因为它使用了require并且没有导出任何内容,所以只执行,而g没有任何价值。

proxyquire尝试

proxyquire似乎允许我更改全局hello变量,但前提是我将其转换为模块调用。

const proxyquire = require('proxyquire')
proxyquire('./global', {'./hello': 'Hello Madam'})

sandboxed-module尝试

此模块似乎可以设置globalslocals,但不能覆盖模块中的现有值。

const SandboxedModule = require('sandboxed-module')
SandboxedModule.require('./global', {
  globals: {hello: 'hello Madam'}
})

1 个答案:

答案 0 :(得分:1)

听起来你想在运行时动态地将“Hello Sir”更改为“Hello World”,在读取模块之后,是吗?

一种方法是将模块作为纯文本读取,而不是使用require,并使用recast之类的工具将其转换为Abstract-Syntax Tree

一旦它是AST,你可以用你喜欢的任何方式修改它,并使用eval动态执行。

hello.js

var hello = 'Hello Sir'

console.log(hello)

recast.js

const recast = require("recast");
const fs = require('fs');

// read the file in as plain text
const code = fs.readFileSync('./hello.js');

// create abstract syntax tree
const ast = recast.parse(code);

// change value of the first variable
ast.program.body[0].declarations[0].init.value = 'Hello World';

// convert AST back to Javascript text
const modifiedSrc = recast.print(ast).code;

// execute modified code
eval(modifiedSrc);

从命令行执行

~/example$ node recast.js
Hello World