[英]Node.js, Mocha, make globals in closures available
我目前正在使用Node設置一些mocha測試,一般來說它們都可以工作。 我現在遇到了一個我無法解決的問題。
我有一個包含以下內容的JS文件:MyClass.js( class MyClass
+ constructor: ->
常規CoffeeScript輸出constructor: ->
)
編輯:這是瀏覽器代碼,我只想用Node來測試它。 (這甚至是可取的嗎?)
(function() {
window.MyClass = (function() {
function MyClass() {
// Do something cool here
}
return MyClass;
})();
}).call(this);
我現在在我的測試文件中需要MyClass.js。 一旦我運行它,它直接拋出一個錯誤
TESTFILE:
var myclass = require('MyClass.js');
...
describe('MyClass', function() { ... });
錯誤:
ReferenceError: window is not defined.
到目前為止,我理解為什么會發生這種情況,Node中不存在窗口。 但我無法想出一個解決方案。 我實際上並不特別需要真正的window
對象,所以我想嘲笑它就足夠了。 但它不是......
var window = {},
myclass = require('myclass.js');
...
describe('MyClass', function() { ... });
這個命令也沒幫助: $ mocha --globals window
我仍然得到同樣的錯誤。 任何想法都非常感謝!
你實際上並不想要窗口對象,你想要的是全局對象。 下面是一些可以在瀏覽器中獲取它的代碼(在這種情況下它將與'window'相同)或在節點中(在這種情況下它將與'global'相同)。
var global = Function('return this')();
然后把事情放在那個而不是'窗口'上。
注意:還有其他獲取全局對象的方法,但這樣做的好處是它也可以在嚴格模式代碼中運行。
使用以下代碼,您可以在Web瀏覽器環境和Node.js中使用類類對象而無需修改。 (抱歉,我不知道如何將其轉換為CoffeeScript)
(function (exports) {
var MyClass = (function() {
function MyClass() {
// Do something cool here
}
return MyClass;
})();
exports(MyClass);
})(function (exported) {
if (typeof module !== 'undefined' && module.exports) {
module.exports = exported;
} else if (typeof window !== 'undefined') {
window.MyClass = exported;
} else {
throw new Error('unknown environment');
}
});
由於您已經擁有不會污染全局名稱空間的范圍,因此可以將其減少為:
(function (exports) {
function MyClass() {
// Do something cool here
}
exports(MyClass);
})(function (exported) {
// see above
});
我不是AMD,require.js和其他模塊加載器的專家,但我認為應該很容易擴展這種模式以支持其他環境。
編輯
在評論中,您說上述解決方案在轉換回CoffeeScript時無法正常工作。 因此,我建議另一種解決方案。 我沒有嘗試過,但也許這可能是解決問題的一種方法:
global.window = {}; // <-- should be visible in your myclass.js
require('myclass.js');
var MyClass = global.window.MyClass;
describe('MyClass', function() {
var my = new MyClass();
...
});
這是一段可怕的代碼,但如果它有效,可能出於測試目的就足夠了。
由於node.js的模塊加載行為,這僅在您的require('myclass.js')
是節點進程中此文件的第一個要求時才有效。 但是在使用Mocha進行測試時,這應該是真的。
1)您正在尋找的是用於在Node中公開內容的module.exports
:
http://openmymind.net/2012/2/3/Node-Require-and-Exports/
2)你也不需要Node中的IIFE,你可以刪除(function() {...
3)你總是可以在Github上查看一些流行的Node repo來查看示例,看看Mocha代碼,因為你正在使用它,你將學到一兩件事。
@hgoebl:由於我不是OP,我無法添加他原來的CoffeeScript代碼,但這是我的例子:
pubsub.coffee:
window.PubSub = window.PubSub || {}
PubSub.subscribe = ( subject, callback )->
現在測試:
assert = require "assert"
pubsub = require './pubsub.coffee'
describe "pubsub.http interface", ->
it "should perform a http request", ->
PubSub.subscribe 1, 2
到目前為止對我有用的是:
window.PubSub = window.PubSub || {}
window.PubSub.subscribe = ( subject, callback )->
和測試:
`window = {}`
assert = require "assert"
pubsub = require './pubsub.coffee'
describe "pubsub.http interface", ->
it "should perform a http request", ->
window.PubSub.subscribe 1, 2
解決方案的主要缺點是,我必須在實現和測試中明確提到window對象。 在瀏覽器中執行的用戶代碼應該能夠省略它。
我現在想出了另一個解決方案:
window = window || exports
window.PubSub = window.PubSub || {}
PubSub = PubSub || window.PubSub
PubSub.subscribe = ( subject, callback )->
然后在測試中,只需要PubSub命名空間:
PubSub = require( './pubsub.coffee' ).PubSub
最后,來自kybernetikos應用的解決方案看起來像這樣:
global = `Function('return this')()`
global.PubSub = global.PubSub || {}
PubSub.subscribe = ( subject, callback )->
現在,PubSub命名空間位於全局命名空間中,只需要包含mocha測試的文件中的簡單需求:
require( './pubsub.coffee' )
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.