There is a module I would like to test. This module writes files to disk using fs.writeFile and fs.mkdir.
I would like the module to not actually write anything during the test to avoid cluttering the filesystem but I would like to make sure fs.writeFile and fs.mkdir are called with the right arguments so that when the code runs in production, the right files are written where I intended them to be.
I got away with using rewire:
var rewire = require('rewire');
var Module = rewire('../lib/module');
var mkdir_path;
var fsMock = {
mkdir: function(path, cb) {
mkdir_path = path;
return cb(null);
}
};
var revert = Module.__set__('fs.mkdir', fsMock.mkdir);
Module.func(function(err) {
assert.equal(mkdir_path, '/expected/path');
revert();
});
This is fine for such a simple example. When there are several calls to fs.mkdir, then I have to use a ton of logic in fsMock.mkdir to make sure that I am only saving mkdir_path for the fs.mkdir call that I want to verify. It turns very ugly and illegible fast.
I have found a way to do it with a sinon stub:
var Module = require('../lib/module');
var sinon = require('sinon');
var fs = require('fs');
var stub = sinon.stub(fs, 'mkdir', function(path, cb) { return cb(null); });
Module.func(function(err) {
assert.equal(stub.calledWith('/expected/path'), true);
fs.mkdir.restore();
});
This still has the issue of requiring a ton of extra logic to make sure I am processing the right fs.mkdir call. Worst, it overrides fs.mkdir globally and forces me to require 'fs' in my test even though I don't need it in my test. If gulp tries to use fs.mkdir before I called restore(), then the stub is used. It doesn't feel like an elegant solution.
Is there an elegant way to test this kind of code? Should I wrap fs.mkdir in a private Module._mkdir method and stub this one out instead of fs.mkdir so I can still assert it was called with the right path, but only globally stub a method that is used by my module only?
Aucun commentaire:
Enregistrer un commentaire