In Javascript/Coffeescript how can I mock out a module's public variable in a test?

℡╲_俬逩灬. 提交于 2019-12-13 05:44:39

问题


I just learned about the module pattern. I've written some code that's gotten sufficiently complex that I want to test a feature. The problem is, I can't figure out how to mock out a value. What follows is coffeescript, but I'll put the generated javascript below so I can get more help. Here's my test that attempts to mock out a field named state, but it always prints "undefined":

root = exports ? this
root.test3 = (->
  root.test2.state = "abc"
  root.test2.doSomething()

  return {}
)()

And here's test2 which for the purpose of this question can be considered the production code:

root = exports ? this
root.test2 = (->
  state = undefined

  doSomething = -> alert state

  return {
    state: state
    doSomething: doSomething
  }
)()

Here's the html I'm running this in, but I don't think it matters:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8"/>
    <title>TEST2</title>

    <script src="test2.js" type="text/javascript"></script>
    <script src="test3.js" type="text/javascript"></script>

    <style>
        canvas {
            border: 1px solid black;
        }
    </style>

</head>

<body>


<h1>This is a test</h1>

</body>
</html>

test2 in Javascript:

var root;

root = typeof exports !== "undefined" && exports !== null ? exports : this;

root.test2 = (function() {
  var doSomething, state;
  state = void 0;
  doSomething = function() {
    return alert(state);
  };
  return {
    state: state,
    doSomething: doSomething
  };
})();

test3 in Javascript:

var root;

root = typeof exports !== "undefined" && exports !== null ? exports : this;

root.test3 = (function() {
  root.test2.state = "abc";
  root.test2.doSomething();
  return {};
})();

As I said, running this alerts undefined. I want it to output "abc". How can I do this?


回答1:


You want to use 'this' in that case,

doSomething = function() {
    return alert(this.state);
};

In your code, 'state' refers to the variable (via closure) which is undefined. You then return an object containing a new 'state' property. You don't need the first 'state' variable, but only the property in your returned object.

'this' in doSomething refers to whatever object it is a part of. In test3, doSomething refers to the returned object with 'state' set to undefined. Once you set state in test3, the object's 'state' property is no longer the same as the private variable 'state' in test2-- it is overwritten in test3.

Essentially, you don't need the module pattern for the effect you desire, there's a much easier way:

root.test2 = {
    state: void 0,
    doSomething: function() {
        return alert(this.state);
    }
};

http://jsfiddle.net/rMJs5/

UPDATE:: I forget all about the Coffee part:

root = exports ? this
root.test2 = (->
  doSomething = -> alert this.state
  return {
    state: undefined
    doSomething: doSomething
  }
)()

Or, simply:

root = exports ? this
root.test2 = {
    state: undefined
    doSomething: -> alert this.state
}


来源:https://stackoverflow.com/questions/17416392/in-javascript-coffeescript-how-can-i-mock-out-a-modules-public-variable-in-a-te

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!