javascript 在 jasmine 中监视 jQuery $('...') 选择器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22060119/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 22:19:07  来源:igfitidea点击:

Spying on jQuery $('...') selector in jasmine

javascriptjqueryunit-testingmockingjasmine

提问by parxier

When it comes to spying on jQuery functions (e.g. bind, click, etc) it is easy:

当涉及到对 jQuery 函数(例如、 等)进行监视时bindclick很容易:

spyOn($.fn, "bind");

The problem is when you want to spy on $('...')and return defined array of elements.

问题是当您想要监视$('...')并返回已定义的元素数组时。

Things tried after reading other related answers on SO:

阅读其他相关答案后尝试的事情:

spyOn($.fn, "init").andReturn(elements); // works, but breaks stuff that uses jQuery selectors in afterEach(), etc
spyOn($.fn, "merge").andReturn(elements); // merge function doesn't seem to exist in jQuery 1.9.1
spyOn($.fn, "val").andReturn(elements); // function never gets called

So how do I do this? Or if the only way is to spy on initfunction how do I "remove" spy from function when I'm done so afterEach()routing doesn't break.

那么我该怎么做呢?或者,如果唯一的方法是监视init函数,我如何在完成后从函数中“删除”间谍,以便afterEach()路由不会中断。

jQuery version is 1.9.1.

jQuery 版本是 1.9.1。

WORKAROUND:

解决方法:

The only way I could make it work so far (ugly):

到目前为止我可以让它工作的唯一方法(丑陋):

realDollar = $;
try {
  $ = jasmine.createSpy("dollar").andReturn(elements);
  // test code and asserts go here
} finally {
  $ = realDollar;
}

采纳答案by Eric

Normally, a spy exists for the lifetime of the spec. However, there's nothing special about destroying a spy. You just restore the original function reference and that's that.

通常,间谍在规范的整个生命周期内都存在。然而,摧毁间谍并没有什么特别之处。您只需恢复原始函数引用即可。

Here's a handy little helper function (with a test case) that will clean up your workaround and make it more usable. Call the unspymethod in your afterEachto restore the original reference.

这是一个方便的小帮助函数(带有测试用例),它将清理您的解决方法并使其更有用。调用unspy您中的方法afterEach以恢复原始引用。

function spyOn(obj, methodName) {
    var original = obj[methodName];
    var spy = jasmine.getEnv().spyOn(obj, methodName);
    spy.unspy = function () {
        if (original) {
            obj[methodName] = original;
            original = null;
        }
    };
    return spy;
}

describe("unspy", function () {
    it("removes the spy", function () {
        var mockDiv = document.createElement("div");
        var mockResult = $(mockDiv);

        spyOn(window, "$").and.returnValue(mockResult);
        expect($(document.body).get(0)).toBe(mockDiv);

        $.unspy();

        expect(jasmine.isSpy($)).toEqual(false);
        expect($(document.body).get(0)).toBe(document.body);
    });
});

As an alternative to the above (and for anyone else reading this), you could change the way you're approaching the problem. Instead of spying on the $function, try extracting the original call to $to its own method and spying on that instead.

作为上述(以及其他阅读本文的人)的替代方案,您可以改变处理问题的方式。与其监视$函数,不如尝试提取$对其自身方法的原始调用并监视它。

// Original
myObj.doStuff = function () {
    $("#someElement").css("color", "red");
};

// Becomes...
myObj.doStuff = function () {
    this.getElements().css("color", "red");
};

myObj.getElements = function () {
    return $("#someElement");
};

// Test case
it("does stuff", function () {
    spyOn(myObj, "getElements").and.returnValue($(/* mock elements */));
    // ...
});

回答by Liam Middleton

By spying on the window itself you have access to any window properties. As Jquery is one of these you can easily mock it as below and return the value you require.

通过监视窗口本身,您可以访问任何窗口属性。由于 Jquery 是其中之一,您可以轻松地模拟它,如下所示并返回您需要的值。

spyOn(window, '$').and.returnValue(mockElement);

Or add a callFake with the input if it needs to be dynamic.

或者如果它需要是动态的,则在输入中添加一个 callFake。