使用命名空间模块范例在Mocha / Chai中编写测试

时间:2012-05-12 16:26:50

标签: node.js coffeescript mocha

我正在编写一系列用于进行数学运算的coffeescript文件,我需要编写一些测试。我认为mocha和chai是要走的路。目前,我使用命名空间方法将所有单独的函数组合在一起,以保持整洁:

namespace = (target, name, block) ->
  [target, name, block] = [(if typeof exports isnt 'undefined' then exports else window), arguments...] if arguments.length < 3
  top    = target
  target = target[item] or= {} for item in name.split '.'
  block target, top

exports? exports.namespace = namespace

我现在要测试的是我的矩阵类,看起来有点像这样:

namespace "CoffeeMath", (exports) ->

  class exports.Matrix4
    for name in ['add', 'subtract', 'multiply', 'divide', 'addScalar', 'subtractScalar', 'multiplyScalar', 'divideScalar', 'translate']
        do (name) ->
          Matrix4[name] = (a,b) ->
          a.copy()[name](b)

    Matrix4.DIM = 4

    # Take a list in column major format
    constructor: (@a=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]) ->
      # etc etc ...

现在使用可爱的coffeescript编译器编译所有这些都很好。我有这样的测试:

chai = require 'chai'
chai.should()

{namespace} = require '../src/aname'
{Matrix4} = require '../src/math'

describe 'Matrix4 tests', ->
  m = null
  it 'should be the identity matrix', ->
    m  = new exports.Matrix4()
    m.a.should.equal '[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]'

问题是,我收到以下错误:

node.js:201
        throw e; // process.nextTick error, or 'error' event on first tick
              ^
ReferenceError: namespace is not defined
    at Object.<anonymous> (/Users/oni/Projects/Saito.js/src/math.coffee:3:3)
    at Object.<anonymous> (/Users/oni/Projects/Saito.js/src/math.coffee:631:4)
    at Module._compile (module.js:441:26)

应该包含aname我相信并导出命名空间函数,所以我不明白为什么没有定义命名空间。有什么想法吗?

1 个答案:

答案 0 :(得分:1)

来自fine manual

  

要导出对象,请添加到特殊的exports对象。

然后,exports is returned by require

  

module.exportsrequire调用后实际返回的对象。

所以,当你这样说时:

namespace = require '../src/aname'

您的测试中有namespace.namespace

CoffeeScript将每个文件包装在function wrapper中,以避免污染全局命名空间:

  

所有CoffeeScript输出都包含在一个匿名函数中:(function(){ ... })();此安全包装器与var关键字的自动生成相结合,使得非常难以意外地污染全局命名空间。

这意味着你在编译的JavaScript中有这样的东西:

(function() {
    exports.namespace = ...
})();
(function() {
    # Matrix4 definition which uses the 'namespace' function
})();
(function() {
    var namespace = ...
})();

结果是namespace在您定义Matrix4的位置不可见,因为测试和Matrix4存在于单独的函数中,因此存在单独的范围。

如果你想在数学文件中使用namespace,那么你必须在那里require而不是require你的数学文件的代码。