thlorenz / proxyquire

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

Globally override a module that returns a function #56

Closed elicwhite closed 9 years ago

elicwhite commented 9 years ago

I know that you can set '@global': true in the stubs for modules that are objects, but how do you do it for modules that return functions. For example:

// main.js
var Deep = require('./deep');

var instance = new Deep();
instance.run();

module.exports = instance;
// deep.js
var deepest = require('./deepest')('My Name');

function Deep() {
}

Deep.prototype = {
  run: function() {
    deepest.baz();
  }
};

module.exports = new Deep();
// deepest.js
function Deepest(name) {
  return {
    baz: function() {
      console.log(name);
    }
  };
}

module.exports = Deepest;

Deepest returns a function that I need to mock out, but since it is used inside of Deep, I have to use @global.

If deepest was exporting the inner object instead of the wrapping function, I could do this:

var main = proxyquire('./main.js', {
  './deepest': {
    '@global': true,
    'baz: function() {}
  }
}

But since deepest returns a function, my understanding is that I have to mock it like this:

var main = proxyquire('./main.js', {
  './deepest': function() {
    return {
      baz: function() {
        console.log('mocked');
      }
    }
  }
}

But I can no longer set '@global' on the mock object. Right? How should I handle this? This situation has arisen because of the api design of a third party module so I sadly can't really restructure these calls.

bendrucker commented 9 years ago

Sure you can! Just assign create a function assigned to a variable and then set deepest['@global'] = true.

var deepest = function () {}
deepest['@global'] = true
elicwhite commented 9 years ago

Neat. Thanks!

thlorenz commented 9 years ago

Seems like we need to add these special cases to the docs and/or a wiki.

bendrucker commented 9 years ago

Sure. I think it merits its own section under API. Wikis don't actually get read. Agreed?

thlorenz commented 9 years ago

Agreed, currently we don't even have a wiki to speak of :)

MarkHerhold commented 8 years ago

@bendrucker This '@global' = true implementation of yours is truly genius! :+1: