0

Let's say, I have app.js

function method(){
 return true;
}

function callMethod(){
 return method();
}
module.exports.method = method;
module.exports.callMethod = callMethod;

And app.spec.js

var app = require(app);

...describe code etc... 

var first = sinon.spy(app,'callMethod');
var second = sinon.spy(app,'method');

app.callMethod();

expect(first.called).to.equal(true); //passed
expect(second.called).to.equal(true); //fails

I'm guessing it's failing because inside my spec file I have a different reference to 'method' than the one that is being called when inside app.js calls it from inside of 'callMethod'.

I've seen this behavior many times before, and I know work arounds, but I was wondering if there was a clean way to actually spy on the method 'method' in this situation without a workaround.

tbh__
  • 324
  • 3
  • 17
  • It depends on what you call a workaround. – robertklep Jun 28 '17 at 20:50
  • @robertklep So I have a workaround that is basically passing a callback to method, through callMethod from the app.spec.js, and I'm able to add a spy to that. I'm really just curious if that is a normal solution for sinon? – tbh__ Jun 29 '17 at 12:11
  • No, when you do that, you're accommodating your code to enable the test, which isn't really a good solution. Sinon is limited in what it can do in situations like this, but you may be able to use [`rewire`](https://github.com/jhnns/rewire). – robertklep Jun 29 '17 at 13:46
  • @robertklep you cannot use `rewire` to replace internal functions to the module, only external dependencies. – oligofren Jun 29 '17 at 13:51
  • @tbh__ Your thoughts on why this does not work are absolutely correct. And as you see, this is not something Sinon can do anything about, it's just how javascript works :) In your comment you say that you solve this by way of sending an optional callback to `callMethod` that replaces the dependency `callMethod` has on on its internal method, `method`. This is called dependency injection. You can see some alternative techniques for doing that here: https://stackoverflow.com/questions/44397639/how-to-test-an-es6-class-that-needs-jquery/44482001#44482001 – oligofren Jun 29 '17 at 13:51
  • 2
    @oligofren you _can_ replace module-internal functions with it, I've used it for exactly that purpose :) (demo here: https://gist.github.com/robertklep/46ffd9d602d30d26677ab9149a1c021d) – robertklep Jun 29 '17 at 14:04
  • @robertklep I guess it's a good thing one can learn something every day... thanks! I can only guess at the kind of AST manipulation required on the parsed module source to achieve that kind of thing. Brrr. – oligofren Jun 29 '17 at 14:43
  • We're giving this a shot in our application, but I think using rewire looks like an acceptable solution. Your gist was very helpful in explaining this. – tbh__ Jun 30 '17 at 15:30

0 Answers0