Consider the following jasmine spec:
describe("something.act()", function() {
it("calls some function of my module", function() {
var mod = require('my_module');
spyOn(mod, "someFunction");
something.act();
expect(mod.someFunction).toHaveBeenCalled();
});
});
This is working perfectly fine. Something like this makes it green:
something.act = function() { require('my_module').someFunction(); };
Now have a look at this one:
describe("something.act()", function() {
it("calls the 'root' function of my module", function() {
var mod = require('my_module');
spyOn(mod); // jasmine needs a property name
// pointing to a function as param #2
// therefore, this call is not correct.
something.act();
expect(mod).toHaveBeenCalled(); // mod should be a spy
});
});
This is the code I'd like to test with this spec:
something.act = function() { require('my_module')(); };
This has bogged me down several times in the last few months. One theoretical solution would be to replace require() and return a spy created with createSpy(). BUT require() is an unstoppable beast: it is a different "copy" of the function in each and every source file/module. Stubbing it in the spec won't replace the real require() function in the "testee" source file.
An alternative is to add some fake modules to the load path, but it looks too complicated to me.
Any idea?
It looks like I found an acceptable solution.
The spec helper:
The spec:
This is not perfect but does the job quite well. It does not even mess with the testee source code, which is kind of a criterion for me.
There is another approach. You can put the module in the global scope by not using
var
when requiring it:You could also wrap the module in another module:
And then obviously make sure that wherever
someFunctionThatShouldCallTheModule
is, you're requiring the wrapper rather than the real module.You can use gently module (https://github.com/felixge/node-gently). Hijacking require is mentioned in examples, and dirty NPM module actively uses it, so I suppose it works.
This was very helpful, but it doesn't support calling through via
.andCallThrough()
.I was able to adapt it though, so I thought I'd share:
I needed to do this today and came across this post. My solution follows:
In a spec helper:
In a spec:
rewire is awesome for this