#angular #typescript #observable #abstract-class #jasmin
Вопрос:
У меня есть абстрактный класс, который помогает избежать повторяющегося кода (для отмены подписки на наблюдаемые объекты), он выглядит так:
export abstract class SubscriptionManagmentDirective implements OnDestroy {
componetDestroyed = new Subject<void>()
constructor() {}
ngOnDestroy(): void {
this.componetDestroyed.next()
this.componetDestroyed.unsubscribe()
}
}
В некоторых случаях случалось, что я переопределял ngOnDestroy
и забывал звонить super.ngOnDestroy()
, а затем подписки сходили с ума.
Я добавил модульный тест к расширяющимся компонентам, чтобы проверить, что были вызваны подписки без подписки, но для этого мне нужно не забыть их добавить.
Мой вопрос таков,
- есть ли способ принудительного вызова, который
super.ngOnDestroy()
вызывается всякий раз, когда компонент расширяется? - или есть способ написать модульный тест для абстрактного класса, который будет проверяться на любом компоненте, расширяющем этот класс?
Любая помощь будет признательна, спасибо.
Ответ №1:
Я думаю, что лучшим подходом к этому было бы добавление "noImplicitOverride": true
в ваш tsconfig. Это не обязательно поможет вам запомнить вызов супер-метода, но это заставит вас четко указывать методы переопределения, что приведет к ошибке компиляции в тех случаях, когда вы переопределяете метод без использования override
ключевого слова. Затем разработчик должен решить, нужно ли вызывать суперметод или нет.
Ответ №2:
- Нет, такого способа автоматического вызова метода из абстрактного не существует.
- Вы должны проводить модульный тест только в изоляции. Просто создайте встроенный тестовый класс, который расширяет ваш абстрактный, а затем модульный тест
ngOnDestroy
. Этого вполне достаточно.
Ответ №3:
Я могу придумать только один способ, очень банальный и уродливый. Одна вещь, которая принудительно выполняется super()
, — это вызов в конструкторе самим машинописным текстом. Поэтому вы могли бы
class Foo {
constructor() {
const oldNgOnDestroy = this.ngOnDestroy;
this.ngOnDestroy = function() {
console.log("decorated ngOnDestroy");
return oldNgOnDestroy();
}.bind(this);
}
ngOnDestroy() {
console.log("original ngOnDestroy");
}
}
class Bar extends Foo {
constructor() {
super();
}
}
class Baz extends Foo {
constructor() {
super();
}
ngOnDestroy() {
console.log("custom ngOnDestroy");
}
}
const bar = new Bar();
bar.ngOnDestroy();
const baz = new Baz();
baz.ngOnDestroy();
Как я уже сказал, халтурно и некрасиво.