Overriding functions in other modules in node.js

2019-04-12 03:37发布

问题:

I'm trying to stub a function with nodeunit in a Node.js app. Here's a simplified version of what I'm trying to do:

In lib/file.js:

var request = require('request');

var myFunc = function(input, callback){
    request(input, function(err, body){
        callback(body);
    });
};

In test/test.file.js:

var file = require('../lib/file');

exports['test myFunc'] = function (test) {
    request = function(options, callback){
        callback('testbody');
    };

    file.myFunc('something', function(err, body){
        test.equal(body, 'testbody');
        test.done();
    });
};

It seems like I'm not overriding request properly, because when I try to run the test, the actual non-stub request is getting called, but I can't figure out what the correct way to do it is.

EDIT:

To expand on Ilya's answer below, with my example above.

in lib/file/js:

module.exports = function(requestParam){
    return {
        myFunc: function(input, callback){
            requestParam(input, function(err, body){
                callback(body);
            });
        }
    }
}

Then in test/test.file.js:

var fakeRequestFunc = function(input, callback){
// fake request function
}

var file = require('../lib/file')(fakeRequestFunc)(
//test stuff
}

回答1:

As you noticed, variables declared in one module, cannot easily be accessed from another module. In such cases, you have two common variants:

1) Declare everything you need in every module (not your case, I suppose)

2) Pass parameters to a function

var ab = "foo",
index = require('/routes/index')(ab);

When you call a function form a module, you may pass it 'request' or any other vars or object you need.



回答2:

I've run into similar issue. After exploring request module code my solution was using request.get instead of request in my code (do exactly the same). And then stub it in test like that: https://github.com/anatoliychakkaev/resizer-app/blob/master/test/resizer.js#L25

It also possible to stub result of 'require' method in nodejs. Check sources on lib/module.js to manage how to do it. It should be something like:

require('module')._cache['/path/to/request.js'] = your_stub

But I don't like this solution because it doesn't work in 100% of cases and may stop working in future versions of node (this is not public api), so you should use this way only in case when it's not possible to use other ways of stubbing.