我将如何存根 fs 回调的注入参数以消除在测试套件中接触文件系统的需要?

How would I stub an fs callback's injected params to remove the need to touch the filesystem in a test suite?

我使用 Chai、Mocha 和 Sinon 作为我的测试框架。

现在,我有一个对此工作的测试,但实际上我必须创建一个目录并将文件放入其中才能让我的测试真正做一些事情(这将是一个大型测试套件,所以用至少可以说,所有这些 diskIO 都不理想)。我怎样才能去掉注入机制,这样我就不必在测试中接触磁盘了?

我在想,在下面的示例代码中,一些方法可以对 fs.readdir 方法注入的 errfiles 参数进行存根。这样,我就避免了在单元测试中测试 fs.readdir 。我做了一些谷歌搜索并查看了 API 文档,但我没有找到我需要的东西(或者不认识它)。

这是我正在谈论的一些示例代码:

测试中的功能

function fsFxnWrapper(dir, callback) {
  var doSomeMutation = function (files) {
    ...
  };

  fs.readdir(dir, function(err, files) {
    callback(err, doSomeMutation(files));
  });
}

示例测试用例

describe('When the directory has things'', function () {
  before(function () {
    ...
  });

  after(function () {
    ...
  });

  // I'm not sure how to write my stubs so that fs.readdir inside of the
  // fsFxnWrapper doesn't have to go out to the filesystem to retrieve something...
  it('should do the proper mutation on the files list', function () {
    var valueAfterMutation = [ /* the expected answer */];
    fsFxnWrapper('test/dir', function (err, files) {
      expect(files).to.deep.equal(valueAfterMutation);
      expect(err).to.equal(null);
    });
  });
});

您可以采用的一种方法是像这样构建您的模块:

var Example = function (fs) {
  fs = fs || require('fs');

  this.fsFxnWrapper = function(dir, callback) {
    var doSomeMutation = function (files) {
      ...
    };

    fs.readdir(dir, function(err, files) {
      callback(err, doSomeMutation(files));
    });
  }
};

module.exports = Example;

然后你可以在将它传递给模块的构造函数之前模拟 fs

describe('When the directory has things'', function () {
  it('should do the proper mutation on the files list', function () {

    var Example = require('Example');
    var fs = require('fs');

    fs.readir = function () {
      // your alternative implementation that doesn't touch the filesystem
    }

    var example = new Example(fs);
    var valueAfterMutation = [ /* the expected answer */];

    example.fsFxnWrapper('test/dir', function (err, files) {
      expect(files).to.deep.equal(valueAfterMutation);
      expect(err).to.equal(null);
    });
  });
});

我很想听听其他人对此的看法,因为我一直在某些地方使用这种方法,虽然它有效,但我不确定是否存在更理想的解决方案。

希望对您有所帮助。

如果您在 Node.js 下工作,您可能会考虑一些模拟库:node-mocks, mock-fs