Question

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 {};
})();

Update

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.

Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top