首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在测试过程中存根node.js内置文件系统?

问如何在测试过程中存根node.js内置文件系统?
EN

Stack Overflow用户
提问于 2013-03-31 01:55:21
回答 11查看 19K关注 0票数 32

我想要存根像fs这样的node.js内置函数,这样我实际上就不会进行任何系统级的文件调用。我能想到的唯一一件事就是将fs和所有其他内置函数作为参数传递给我的所有函数,以避免使用真正的fs。这看起来有点愚蠢,并且创建了一个冗长的函数签名,里面挤满了作为参数的内置函数。

代码语言:javascript
复制
var fs = require('fs');

function findFile(path, callback) {
  _findFile(fs, path, callback);
}

function _findFile(fs, path, callback) {
  fs.readdir(path, function(err, files) {
     //Do something.
  });
}

然后在测试期间:

代码语言:javascript
复制
var stubFs = {
  readdir: function(path, callback) {
     callback(null, []);
  }
};

_findFile.(stubFs, testThing, testCallback);

有比这更好的方法,对吧?

EN

回答 11

Stack Overflow用户

回答已采纳

发布于 2013-03-31 07:26:36

我喜欢使用rewire来清除需要的存根(...)语句

被测模块

module-a.js

代码语言:javascript
复制
var fs = require('fs')
function findFile(path, callback) {
  fs.readdir(path, function(err, files) {
     //Do something.
  })
}

测试代码

module-a-test.js

代码语言:javascript
复制
var rewire = require('rewire')
var moduleA = rewire('./moduleA')
// stub out fs
var fsStub = {
  readdir: function(path, callback) {
     console.log('fs.readdir stub called')
     callback(null, [])
  }
}
moduleA.__set__('fs', fsStub)
// call moduleA which now has a fs stubbed out
moduleA()
票数 23
EN

Stack Overflow用户

发布于 2016-10-28 21:59:18

如果被测试的模块是调用fs本身的模块,那么重新连接和其他存根解决方案是很好的。然而,如果测试下的模块使用了底层使用fs的库,那么重新布线和其他存根解决方案很快就会变得混乱。

现在有一个更好的解决方案:mock-fs

mock-fs模块允许节点的内置fs模块由内存中的模拟文件系统临时备份。这使您可以针对一组模拟文件和目录运行测试,而不是拖着一堆测试夹具。

示例(厚颜无耻地从自述文件中删除):

代码语言:javascript
复制
var mock = require('mock-fs');

mock({
  'path/to/fake/dir': {
    'some-file.txt': 'file content here',
    'empty-dir': {/** empty directory */}
  },
  'path/to/some.png': new Buffer([8, 6, 7, 5, 3, 0, 9]),
  'some/other/path': {/** another empty directory */}
});
票数 14
EN

Stack Overflow用户

发布于 2013-03-31 07:55:26

另一种选择(尽管我认为Noah的rewire建议更好):

围绕require编写一个包装器,名为requireStubbable左右。在测试设置代码中,将其放入一个只需配置一次的模块中。因为节点缓存了require的结果,所以每当您再次需要requireStubbable模块时,您都会得到相同的配置函数。您可以对其进行配置,以便将任意数量的模块存根,所有其他模块将原封不动地传递下去。

但是,您希望支持传入存根的任何模块都需要使用requireStubbable函数,而不是常规的require。rewire模块没有这个缺点,而是将控制权交给调用代码。

4月26日添加

我从来没有意识到,但是由于require("fs")返回的对象(或者更准确地说:对象引用)是缓存的,您可以简单地这样做:

代码语言:javascript
复制
const fs = require("fs")
fs.readFile = function (filename, cb) {
  cb(null, new Buffer("fake contents"));
};
// etc

当您在任何地方包含此代码时,fs.readFile将在任何地方指向上面的函数。这适用于清除任何纯粹是函数集合的模块(就像大多数内置模块一样)。如果模块返回一个唯一的函数,那么它不能工作的情况。要做到这一点,像rewire这样的东西是必要的。

票数 11
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15721619

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档