Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

add the possibility to intercept require() calls #26

Closed
wants to merge 1 commit into from

Conversation

jankuca
Copy link

@jankuca jankuca commented Mar 23, 2014

These two functions make it possible to inject mock modules required after the host module is loaded.

If for instance a module has a method which requires another module in its logic, it is possible to inject the mock there:

// x.js:
exports.getModule = function () {
    return require("abc");
};

Even though the require call occurs after the module load, we can alter the results:

var theModule = require('./x.js');
theModule.__setRequiredModule__("abc", abc);
assert(theModule.getModule() === abc);

These two function make it possible to inject mock modules required after the host module is loaded.

If for instance a module has a method which requires another module in its logic, it is possible to inject the mock there:

    exports.getModule = function () {
        return require("abc");
    };

Even though the require call occurs after the module load, we can alter the results:

    theModule.__setRequiredModule__("abc", abc);

    assert(theModule.getModule() === abc);
@jhnns
Copy link
Owner

jhnns commented Mar 25, 2014

First of all: thanks for your effort! You even included tests 👍

Unfortunately I'm not quite convinced. I understand your motivation because you'd like to simply swap the required module with a mock, but your solution will only work if the dependency is required after the module has been initialized. But most of the time - and I even consider it to be best practice - dependencies are required on initialization.

One thing I like about the way rewire works is that dependencies are resolved as usual and swapped after initialization which reveals errors like "module cannot be resolved". But this approach of course implies that all require() calls are done in the top-level scope of the module and that no logic is executed on module initialization.

I discussed this topic some months ago in this issue.

However, I do think that it's possible to swap the module's dependencies on initialization since rewire has access to the private scope of the module and thus can override the require()-function. The api could look like:

var myModule = rewire("./myModule", {
    "fs": fsMock,
    "../other/module.js": otherModuleMock
});

Need to think about it. Any thoughts anyone? 😁

@sokra
Copy link
Contributor

sokra commented Mar 25, 2014

@jhnns You can use sandboxed-module with a rewire sourceTransformers.

@jhnns
Copy link
Owner

jhnns commented Mar 25, 2014

Thx, but I know sandboxed-module. One key feature of rewire is that it doesn't use vm and is trying to emulate node's module environment. Instead of that it uses node's internal module-module to compile the rewired module, so everything is as if it would be required conventionally.

@jankuca
Copy link
Author

jankuca commented May 10, 2014

Um, nevermind.

I was using the added methods for mocking of JSON files loaded via require() but I replaced this with mock-fs and it works flawlessly.

Feel free to merge this later if you find it useful but I do not need the feature anymore. Cheers!

@jankuca jankuca closed this May 10, 2014
@jhnns
Copy link
Owner

jhnns commented May 12, 2014

Yep, mock-fs is probably the better choice for your use-case. Anyway, thanks! 😄

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants