如何在不污染全局命名空间的情况下公开 javascript 对象以进行单元测试

我有一个 javascript 自动完成插件,它使用以下类(用 coffeescript 编写):Query、Suggestion、SuggestionCollection 和 Autocomplete.这些类中的每一个都有一个用 Jasmine 编写的相关规范.

I have a javascript autocomplete plugin that uses the following classes (written in coffeescript): Query, Suggestion, SuggestionCollection, and Autocomplete. Each of these classes has an associated spec written in Jasmine.

插件在模块中定义,例如:

The plugin is defined within a module, e.g.:

(function(){
  // plugin...
}).call(this);

这可以防止类污染全局命名空间,但也可以将它们隐藏在任何测试中(使用 jasmine 的规范,或使用 q-unit 之类的单元测试).

This prevents the classes from polluting the global namespace, but also hides them from any tests (specs with jasmine, or unit-tests with something like q-unit).

在不污染全局命名空间的情况下公开 javascript 类或对象以进行测试的最佳方法是什么?

What is the best way to expose javascript classes or objects for testing without polluting the global namespace?

我会用我想出的解决方案来回答,但我希望有更标准的东西.

I'll answer with the solution I came up with, but I'm hoping that there is something more standard.

更新:我尝试过的解决方案

因为我是 < 的新手100 xp,8 小时内我无法回答自己的问题.我不会等待,而是添加我在这里所做的.

Because I'm a newb with < 100 xp, I can't answer my own question for 8 hours. Instead of waiting I'll just add what I did here.

为了规范这些类,我发明了一个名为 _test 的全局对象,我公开了其中的所有类以进行测试.例如,在咖啡脚本中:

In order to spec these classes, I invented a global object called _test that I exposed all the classes within for testing. For example, in coffeescript:

class Query
  // ...

class Suggestion
  // ...

// Use the classes

// Expose the classes for testing
window._test = {
  Query: Query
  Suggestion: Suggestion
}

然后,在我的规范中,我可以揭示我正在测试的类:

Inside my specs, then, I can reveal the class I'm testing:

Query = window._test.Query

describe 'Query', ->
  // ...

这样做的好处是只有 _test 对象被污染,不太可能与该对象的另一个定义发生冲突.不过,它仍然没有我想要的那么干净.我希望有人能提供更好的解决方案.

This has the advantage that only the _test object is polluted, and it is unlikely it will collide with another definition of this object. It is still not as clean as I would like it, though. I'm hoping someone will provide a better solution.

推荐答案

我认为类似于 CommonJS 模块系统(由 brunch,例如)会起作用.

I think something like the CommonJS module system (as used by brunch, for example) would work.

您可以将代码分成模块,需要它们的部分将通过 require 导入它们.唯一被污染"的部分是模块管理代码维护的模块映射,与您的 test 对象非常相似.

You can separate your code into modules, and the parts that need them would import them via require. The only part that gets "polluted" is the module map maintained by the module management code, very similar to your test object.

Autocomplete.coffee

class exports.Query
// ...

class exports.Suggestion
// ...

然后在 Autocomplete.spec.coffee

{Query, Suggestion} = require 'app/models/Autocomplete'

describe 'Query', ->

相关文章