thlorenz / proxyquire

🔮 Proxies nodejs require in order to allow overriding dependencies during testing.
MIT License
2.75k stars 100 forks source link

Simulating module initialization side-effects #140

Closed minrwhite closed 8 years ago

minrwhite commented 8 years ago

Currently as far as I can tell, there is no way to mock side-effects in the initialization code of proxied modules. Example:

requiredmodule.js

module.exports = { foo: function () {}}

// ... other initialization code ...
if(somethingWentWrong) {
  throw new Error ("Something went wrong");
}

testedmodule.js

module.exports = {function bar() {
  var included;
  try {
    included = require('./requiredmodule.js');
  }
  catch (error) {
    // handle the error here
    return false;
  }
  included.foo();
  return true;
}}

testedmodule-test.js

var proxyquire = require('proxyquire').noCallThru();

describe('Testedmodule.bar', function() {
  it('should handle an initialization error thrown by a required module correctly', function() {
    var stubbedmodule = {
      'foo': function() { /* spy here */ },
      // ==== how do I specify the initialization code to make it error? ===
    };
    var testedmodule = proxyquire('testedmodule.js', {
      'requiredmodule.js': stubbedmodule
    });

    (function (){return testedmodule.bar()}).should.not.throw();
    (function (){return testedmodule.bar()}).should.equal(false);
    // also assert stubbedmodule.foo() not called
  });
});

Initially I was considering making a pull request to allow a replacement module to be specified as a string, but I saw that the tests explicitly handle the case where a module is a string so in order to simulate initialization code, I propose a @initialization property in a similar vein to @noCallThru that would allow one to specify code that would be run as if at the point of the initial require.

Thoughts? If this is seen as valuable effort, I'm happy to start work on a PR for this.

bendrucker commented 8 years ago

The whole point of focusing on modules is to eliminate side effects where possible since they're so hard to test. Allowing users to override code instead of just the module exports themselves would not be in the spirit of proxyquire and would add a bunch of complexity.