Testing Node.js, digging out and testing the module that was needed?

I am struggling to write high quality tests around my node modules. The problem is that a modular system is required. I want to be able to verify that some required module has a method or its state has changed. There seem to be 2 relatively small libraries that can be used here: node-gently and mockery . However, due to their low “profile”, this makes me think that either people are not checking this, or there is another way to do this that I don’t know about.

What is the best way to mock and test the module that was needed?

+6
source share
3 answers

----------- UPDATE ---------------

node-sandbox works on the same principles as below, but ends in a good module. I am very pleased to work with.


--------------- detailed awnser ---------------

After much testing, I found the best way to test node modules in isolation, while the mocking thing is to use the Vojta Jina method to run each module inside vm with a new context, as described here .

with this vm testing module:

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 // ie 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; }; 

you can test each module with its own context and easily drown out all external dependencies.

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

I highly recommend this method for writing effective tests in isolation. Only acceptance tests should hit the entire stack. Unit and integration tests should test individual parts of the system.

+10
source

I think the pattern of bullying is fine. However, I usually prefer to send dependencies as function parameters (similar to passing dependencies in the constructor).

 // foo.js module.exports = function(dep1, dep2) { return { bar: function() { // A function doing stuff with dep1 and dep2 } } } 

When testing, I can send empty objects to mocks instead, whatever is appropriate. Please note: I do not do this for all the dependencies, mostly just IO - I do not feel the need to verify that my code calls path.join or something else.

I think the “low profile” that makes you nervous is due to several things:

  • Some people build their code similar to mine
  • Some people have their own helper, performing the same task as mockery et al (this is a very simple module).
  • Some people do not do unit test such things, instead spin up an instance of their application (and db, etc.) and check for it. Clean tests, and the server is so fast that it does not affect the performance of the test.

In short, if you think bullying is right for you, go for it!

+5
source

You easily fake a request using "a": https://npmjs.org/package/a

 //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 
+1
source

Source: https://habr.com/ru/post/909981/


All Articles