Шпионаж за селектором 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 с входом, если он должен быть динамическим.