Ответ 1
Вам нужно понять механику, стоящую за Typescript и шпионажем.
Сначала на Typescript...
Я игнорирую дополнительные парнеры в class Parent()
.
Typescript использует прототипное наследование за занавеской. Таким образом, прототип скопирует ссылочные свойства из "базового класса" в новый класс. Это то, что цикл for
выполняет в __extends()
.
Это код ES5, ваш Typescript переведен на:
var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var Parent = (function () {
function Parent() {
}
Parent.prototype.buyFood = function () {
// buy food
};
return Parent;
}());
var Husband = (function (_super) {
__extends(Husband, _super);
function Husband() {
return _super.apply(this, arguments) || this;
}
Husband.prototype.makeDinner = function () {
_super.prototype.buyFood.call(this);
// make dinner;
};
return Husband;
}(Parent));
Вы можете перевести Typescript с помощью Typescript игровой площадки.
Ваше выражение super
вызывает метод buyFood()
родительского класса, а не метод "унаследованного" Husband
.
См. строку
_super.prototype.buyFood.call(this);
и следуйте указаниям _super
.
Теперь Жасминские шпионы...
Шпион заменит именованную функцию переданного объекта функцией spy, которая будет действовать как прокси. Этот прокси-сервер теперь может отслеживать вызовы и, в зависимости от запрограммированного поведения, контролировать, следует ли вызывать исходную функцию, подделку, вернуть значение или ничего не делать (по умолчанию).
Очень упрощенная spyOn()
может выглядеть так:
function spyOn(obj, fn) {
var origFn = obj[fn],
spy = function() {
spy.calls.push(arguments);
};
spy.calls = [];
obj[fn] = spy;
}
фактический метод шпиона гораздо более сложный.
Ваша строка
spyOn(husband, 'buyFood');
фактически заменит метод в экземпляре Husband
шпионом. Но поскольку код вызывает ссылку базового класса (родительский прототип), это не та же самая функция, которую вы только что заменили.
Решение
Вы должны либо вызвать метод this
class Husband extends Parent {
makeDinner() {
// call byFood() via this
this.buyFood();
}
}
... или spy на исходном прототипе (super
):
it('Should make a good dinner', () => {
spyOn(Parent.prototype, 'buyFood');
husband.makeDinner();
expect(Parent.prototype.buyFood).toHaveBeenCalled();
}