Шпионаж за селектором jQuery $('...') в jasmine

когда дело доходит до шпионажа за функциями jQuery (например,bind, click, etc) легко:

spyOn($.fn, "bind");

проблема в том, когда вы хотите, чтобы шпионить за $('...') и возвращает определенный массив элементов.

вещи пробовали после прочтения других связанных ответов на 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

Итак, как мне это сделать? Или если единственный способ-шпионить за init функция как "удалить" шпиона из функции, когда я это сделаю afterEach() маршрутизация не ломается.

в jQuery версия 1.9.1.

решение:

единственный способ заставить его работать до сих пор (уродливый):

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

2 ответов


обычно шпион существует в течение всего срока службы спецификации. Однако в уничтожении шпиона нет ничего особенного. Вы просто восстанавливаете исходную ссылку на функцию,и все.

вот удобная маленькая вспомогательная функция (с тестовым случаем), которая очистит ваш обходной путь и сделает его более удобным. Вызовите 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);
    });
});

в качестве альтернативы вышеизложенному (и для всех, кто читает это), вы это может изменить ваш подход к проблеме. Вместо того, чтобы шпионить за $ функция, попробуйте извлечь исходный вызов $ к своему собственному методу и шпионажу вместо этого.

// 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 */));
    // ...
});

шпионя за самим окном, вы получаете доступ к любым свойствам окна. Поскольку Jquery является одним из них, вы можете легко издеваться над ним, как показано ниже, и возвращать требуемое значение.

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

или добавьте callFake с входом, если он должен быть динамическим.