Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Unit testing 测试Node.js,模拟并测试所需的模块?_Unit Testing_Testing_Node.js_Mocking_Require - Fatal编程技术网

Unit testing 测试Node.js,模拟并测试所需的模块?

Unit testing 测试Node.js,模拟并测试所需的模块?,unit-testing,testing,node.js,mocking,require,Unit Testing,Testing,Node.js,Mocking,Require,我正在努力围绕我的节点模块编写高质量的测试。问题在于require模块系统。我希望能够检查某个必需的模块是否有方法或其状态是否已更改。这里似乎有两个相对较小的库可以使用:和。然而,由于他们的低调,这让我觉得要么人们不测试这个,要么有另一种我不知道的方法 模拟和测试所需模块的最佳方法是什么?我认为模拟模式很好。也就是说,我通常选择将依赖项作为参数发送给函数(类似于在构造函数中传递依赖项) 在测试时,我可以发送模拟,而不是空对象,任何看起来合适的东西。请注意,我并不是对所有依赖项都这样做,基本上只有

我正在努力围绕我的节点模块编写高质量的测试。问题在于require模块系统。我希望能够检查某个必需的模块是否有方法或其状态是否已更改。这里似乎有两个相对较小的库可以使用:和。然而,由于他们的低调,这让我觉得要么人们不测试这个,要么有另一种我不知道的方法


模拟和测试所需模块的最佳方法是什么?

我认为模拟模式很好。也就是说,我通常选择将依赖项作为参数发送给函数(类似于在构造函数中传递依赖项)

在测试时,我可以发送模拟,而不是空对象,任何看起来合适的东西。请注意,我并不是对所有依赖项都这样做,基本上只有IO——我觉得没有必要测试我的代码是否调用了
path.join
或其他任何东西

我认为让你紧张的“低调”是由以下几点造成的:

  • 有些人的代码结构与我的类似
  • 有些人有自己的助手来实现与mockery等人相同的目标(这是一个非常简单的模块)
  • 有些人不会对这些东西进行单元测试,而是旋转他们的应用程序(和db等)的实例并进行测试。更干净的测试,而且服务器速度非常快,不会影响测试性能
简言之,如果你认为嘲弄适合你,那就去吧


-----------更新---------------

工作原理与下面所述相同,但被封装在一个漂亮的模块中。我发现和你一起工作很愉快


---------------详细的awnser---------------

经过多次试验,我发现在模拟过程中隔离测试节点模块的最佳方法是使用Vojta Jina的方法,在vm中使用新上下文运行每个模块,如前所述

使用此测试vm模块:

var vm = require('vm');
var fs = require('fs');
var path = require('path');

/**
 * Helper for unit testing:
 * - load module with mocked dependencies
 * - allow accessing private state of the module
 *
 * @param {string} filePath Absolute path to module (file to load)
 * @param {Object=} mocks Hash of mocked dependencies
 */
exports.loadModule = function(filePath, mocks) {
  mocks = mocks || {};

  // this is necessary to allow relative path modules within loaded file
  // i.e. requiring ./some inside file /a/b.js needs to be resolved to /a/some
  var resolveModule = function(module) {
    if (module.charAt(0) !== '.') return module;
    return path.resolve(path.dirname(filePath), module);
  };

  var exports = {};
  var context = {
    require: function(name) {
      return mocks[name] || require(resolveModule(name));
    },
    console: console,
    exports: exports,
    module: {
      exports: exports
    }
  };

  vm.runInNewContext(fs.readFileSync(filePath), context);
  return context;
};
可以使用自己的上下文测试每个模块,并轻松地剔除所有外部依赖项

fsMock = mocks.createFs();
mockRequest = mocks.createRequest();
mockResponse = mocks.createResponse();

// load the module with mock fs instead of real fs
// publish all the private state as an object
module = loadModule('./web-server.js', {fs: fsMock});

我强烈建议用这种方法单独编写有效的测试。只有验收测试才能覆盖整个堆栈。单元测试和集成测试应该测试系统的独立部分。

您可以使用“a”轻松模拟所需:


问题是单元测试击中了数据库,这并不理想。@beck:只有在测试时发送一个真正的db时才可以。谢谢你的回答!然而,我还有另一个问题:我无法利用这项技术在正在测试的模块中用我自己的自定义函数重写私有函数。它产生两个函数:一个在本地范围,另一个在全局范围,被测模块总是调用全局/原始版本。
fsMock = mocks.createFs();
mockRequest = mocks.createRequest();
mockResponse = mocks.createResponse();

// load the module with mock fs instead of real fs
// publish all the private state as an object
module = loadModule('./web-server.js', {fs: fsMock});
//Example faking require('./foo') in unit test:
var fakeFoo = {};
var expectRequire = require('a').expectRequire;
expectRequire('./foo).return(fakeFoo);


//in sut:
var foo = require('./foo); //returns fakeFoo