This is just like my previous question but this is about functions instead of variables. I've got a module and I want to mock out a function in it. Here's my coffeescript code:
root = exports ? this
root.prod = (->
iWantToBeMocked = -> alert "production"
doSomething = -> iWantToBeMocked()
return {
doSomething: doSomething
iWantToBeMocked: iWantToBeMocked
}
)()
root.test = (->
root.prod.iWantToBeMocked = -> alert "I mocked this"
root.prod.doSomething()
return {}
)()
This alerts "production" but I want it to alert "I mocked this". How can I do this?
Here's the javascript that gets output:
var root;
root = typeof exports !== "undefined" && exports !== null ? exports : this;
root.prod = (function() {
var doSomething, iWantToBeMocked;
iWantToBeMocked = function() {
return alert("production");
};
doSomething = function() {
return iWantToBeMocked();
};
return {
doSomething: doSomething,
iWantToBeMocked: iWantToBeMocked
};
})();
root.test = (function() {
root.prod.iWantToBeMocked = function() {
return alert("I mocked this");
};
root.prod.doSomething();
return {};
})();
I've figured out how to solve my problem on my own by applying the answer for my original question:
root = exports ? this
root.prod = (->
iWantToBeMocked = -> alert "production"
doSomething = -> this.iWantToBeMocked()
return {
doSomething: doSomething
iWantToBeMocked: iWantToBeMocked
}
)()
root.test = (->
root.prod.iWantToBeMocked = -> alert "I mocked this"
root.prod.doSomething()
return {}
)()
Notice the this
in this line: doSomething = -> this.iWantToBeMocked()
. But there's still a question here to be answered. I don't understand why I have to use this
here. I'd like someone to explain to me the difference between doSomething = -> this.iWantToBeMocked()
and doSomething = -> iWantToBeMocked()
in the context of mocking.
In your prod
object, you have 2 objects with the name iWantToBeMocked
. The first is the variable containing the function with your original alert; the second is contained in the returned object.
The var iWantToBeMocked
inside root.prod
is a private variable. When you set root.prod.iWantToBeMocked
, you are changing the returned function but are not touching the private member.
Now, when you use
doSomething = -> this.iWantToBeMocked()
doSomething
will look for a method attached to the context this
which happens to be root.prod
, so instead of calling the private iWantToBeMocked
it will call root.prod.iWantToBeMocked
.