I know it isn't working because it calls the original doStuff instead
of a mocked/stubbed doStuff.
That is because function run()
in a.js invokes function doStuff(data)
inside the closure function run()
is holding over the content of a.js and not function doStuff(data)
in a_spec.js.
Illustration by example
Lets re-write a.js to:
var a = 'I am exported';
var b = 'I am not exported';
function foo () {
console.log(a);
console.log(this.b)
}
module.exports.a=a;
module.exports.foo=foo;
and a.spec.js to:
var one = require('./one');
console.log(one); // { a: 'I am exported', foo: [Function: foo] }
one.a = 'Charles';
one.b = 'Diana';
console.log(one); // { a: 'Charles', foo: [Function: foo], b: 'Diana' }
Now if we invoke one.foo()
it will result in:
I am exported
Diana
The I am exported
is logged to the console because console.log(a)
inside foo
points to var a
inside the closure foo
is holding over the contents of a.js.
The Diana
is logged to the console because console.log(this.b)
inside foo
points to one.b
in a.spec.js.
So what do you need to do to make it work?
You need to change:
module.exports = (function () {
return {
run,
doStuff
};
function run() {
return api()
.then((data) => {
return doStuff(data);
})
}
function doStuff(data) {
return `Got data: ${data}`;
}
})()
to:
module.exports = (function () {
return {
run,
doStuff
};
function run() {
return api()
.then((data) => {
return this.doStuff(data); // ´this.doStuff´ points to ´doStuff´ in the exported object
}.bind(this)) // to ensure that ´this´ does not point to the global object
}
function doStuff(data) {
return `Got data: ${data}`;
}
})()