茉莉花模拟窗口对象

toy*_*toy 42 javascript mocking jasmine

我如何模拟窗口对象?我正在做firefox扩展,我想用jasmine进行javascript测试.

在我的JavaScript中我有


function submit() {
...
var url = window.arguments[0];
...
}

显然,我必须在jasmine中模拟window.arguments [0],因为如果不从window.openDialog传递任何参数,该对象就不存在

这是我试图用"with"嘲笑它


it("should submit to server", function() {

        var localContext = {
            "window": {
                arguments: ["http://localhost"]
            }

        }

        with(localContext);

但是我仍然得到这个错误TypeError:无法读取未定义的属性'0',就像测试运行时一样window.arguments [0]被真实窗口消除了,因为如果我做的话

window.arguments[0]

在测试中,它正确打印出"http:// localhost".但是当涉及到submit()方法时,它会显示window.argument未定义的错误.

And*_*rle 61

问题是你只是覆盖了窗口对象的属性.如果你能做到这一点,浏览器也可以做到这一点.因此,模仿每个人都可以访问的全局对象的函数或属性通常不是一个好主意,因为当您尝试访问它们时,您永远无法确定您的更改是否存在.

这让我想到依赖注入.它是一种使代码单元可测试的常见模式,重点是单元.这是什么意思.无论何时创建新对象或访问全局对象,您不仅要测试单元功能,还要测试新创建的或全局对象的功能.要预先添加,请不要在单元中创建新对象,而是将其传递给.通常你会在构造函数中使用它,但是在JavaScript函数中是具有函数体作为构造函数的对象,你也可以将依赖项简单地传递给你的函数.

因此,在您的情况下,该函数取决于全局窗口对象.因此,不要尝试访问全局窗口对象,而是将其作为参数传递给函数.这样做你可以传入生产代码中的window对象和一个带有参数属性的简单JavaScript对象到你的测试中:

function youWannaTest(w){
    console.log(w.arguments[0]);
}
Run Code Online (Sandbox Code Playgroud)

在你的扩展中调用这样的函数:

youWannaTest(window);
Run Code Online (Sandbox Code Playgroud)

在你的测试中调用这样的函数:

youWannaTest({arguments: ['someValue']});
Run Code Online (Sandbox Code Playgroud)


A.W*_*ams 5

我也认为依赖注入是最干净的解决方案。

你的JS:

function submit(_window) {
    _window = _window || window
    ...
    var url = _window.arguments[0];
    ...
}
Run Code Online (Sandbox Code Playgroud)

您的单元测试:

it('works like a dream', function () {
    var _window = { arguments: ['url'] }
    expect(submit(_window)).toBeTotallyAwesome()
})
Run Code Online (Sandbox Code Playgroud)