Что я хочу сделать: мы пишем несколько тестов для существующей базы кода Javascript, в которой интенсивно используется jQuery. Для тестов нам не нужны настоящие HTML-элементы (HTML-фикстуры). Мы бы предпочли, чтобы у нас был фиктивный объект jQuery, который не делает ничего, связанного с HTML.
Моя отправная точка: наиболее многообещающий подход, который я нашел здесь:
http://eclipsesource.com/blogs/2014/03/27/mocks-in-jasmine-tests/
Это создает вспомогательный метод, который создает макет, просматривая функции объекта и создавая шпион для каждой функции:
window.mock = function (constr, name) {
var keys = [];
for (var key in constr.prototype)
keys.push( key );
return keys.length > 0 ? jasmine.createSpyObj( name || "mock", keys ) : {};
};
Затем, если я правильно его понял, он использует это так (адаптированный пример из его сообщения в блоге):
var el = mock($);
el('.some-not-existing-class').css('background', 'red');
expect(el.css).toHaveBeenCalledWith('background', 'red');
Однако это не работает, так как el
является object
, а не function
.
Мой подход к решению этой проблемы: я реорганизовал его функцию mock
, чтобы учесть случай, когда constr
является function
:
mock (constr, name) {
var keys = [];
for (var key in constr.prototype)
keys.push(key);
var result = keys.length > 0 ? jasmine.createSpyObj(name || "mock", keys) : {};
// make sure that if constr is a function (like in the case of jQuery), the mock is too
if (typeof constr === 'function') {
var result2 = result;
result = jasmine.createSpy(name || 'mock-fn');
for (var key in result2)
result[key] = result2[key];
}
return result;
}
Однако вторая строка в тесте выдает ошибку Cannot read property css of undefined
:
var el = mock($);
el('.some-not-existing-class').css('background', 'red');
expect(el.css).toHaveBeenCalledWith('background', 'red');
Другие идеи: я также пытался объединить шпионский объект с jQuery, но это тоже не помогло.
Любые идеи? Надеюсь, мы не единственные, кто делает это без HTML-фикстур.