Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I stub node.js built-in fs during testing?

I want to stub node.js built-ins like fs so that I don't actually make any system level file calls. The only thing I can think to do is to pass in fs and all other built-ins as an argument to all of my functions to avoid the real fs from being used. This seems a little bit silly and creates a verbose function signature crowded with built ins as arguments.

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.   }); } 

And then during testing:

var stubFs = {   readdir: function(path, callback) {      callback(null, []);   } };  _findFile.(stubFs, testThing, testCallback); 

There's a better way than this right?

like image 441
Bjorn Avatar asked Mar 30 '13 17:03

Bjorn


2 Answers

I like using rewire for stubbing out require(...) statements

Module Under test

module-a.js

var fs = require('fs') function findFile(path, callback) {   fs.readdir(path, function(err, files) {      //Do something.   }) } 

Test Code

module-a-test.js

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() 
like image 152
Noah Avatar answered Oct 06 '22 09:10

Noah


Rewire and other stubbing solutions are good if the module under test is the one making calls to fs itself. However, if the module under test uses a library which uses fs underneath, rewire and other stubbing solution get hairy pretty quickly.

There is a better solution now: mock-fs

The mock-fs module allows Node's built-in fs module to be backed temporarily by an in-memory, mock file system. This lets you run tests against a set of mock files and directories instead of lugging around a bunch of test fixtures.

Example (shamelessly lifted from its readme):

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 */} }); 
like image 39
Mrchief Avatar answered Oct 06 '22 09:10

Mrchief