用mock函数替换nodejs模块中的函数

时间:2015-08-01 16:06:14

标签: javascript json node.js unit-testing nodeunit

我在nodejs中创建了一个小项目,它是API的包装器。我正在使用nodeunit编写一些单元测试,需要将各种模拟函数注入模块(例如,模拟向服务器发出HTTP请求并输出各种不同响应以测试我的代码的函数)。

我的问题是如何将这些功能注入我的模块?

我已经确定了理论上应该如下工作的两种方法:

方法1

重命名我要替换的模块的文件夹,并添加一个包含我要注入的代码的新文件夹,例如:

./node_modules/request -> ./node_modules/request.tmp
./tests/myRandomFunction -> ./node_modules/request

执行测试后,我会做相反的事情:

./node_modules/request -> ./tests/myRandomFunction
./node_modules/request.tmp -> ./node_modules/request

这看起来相当hacky,并不是我想尝试的东西,即使它理论上应该有效。

方法2

这是我使用模块初始化的首选方法。我的模块采用一个JSON对象,可以包含各种选项,如下所示:

var module = require('./module')({
  option1: '',
  option2: '',
  ...
});

我打算在这个名为'_testing'的JSON对象中添加一个键,其中包含一个包含各种函数的JSON对象的值,例如:

var module = require('./module')({
  _testing: {
    request: function() {return false;}
  }
});

在我的模块中,我可以执行以下操作:

  • 如果this._testing存在且是JSON对象
  • 循环遍历此._testing
  • 对于this._testing中的每个键
  • 使用与其值相同的名称替换该函数,例如

eval(''+key+' = this._testing.'+key) //eval('request = this._testing.request')
/*
eval can be dangerous I should probably perform some validation for example is key a function we want to be replaced? Can I check if nodeunit is testing my module and if it isn't don't do anything?
*/

是否有更好的方法在我的模块中注入/替换功能以进行测试?

2 个答案:

答案 0 :(得分:1)

我为此目的使用了Mockery

用于测试HTTP调用Nock

他们都提供了更清洁的方法

答案 1 :(得分:1)

这称为“嘲弄”或“剔除”。这是测试时的常见必需品,并且有各种各样的库。可能最受欢迎的是Sinon

使用Sinon,您可以执行类似var stub = sinon.stub(request, [methodName]).returns(false)(或任何其他返回值)的操作。您还可以执行stub.expects(42)之类的操作来断言函数在调用时将其作为参数接收。