如何对Angular中的退订功能进行单元测试 [英] How to unit test unsubscribe function in angular
问题描述
我想找到一种方法来测试对订阅"和主题"的取消订阅功能的调用.
I would like to find a way to test unsubscribe function calls on Subscriptions and Subjects.
我提出了一些可能的解决方案,但是每个解决方案都有其优缺点.请记住,我不想出于测试目的而更改变量的访问修饰符.
I came up with a few possible solutions, but every one of these have pros and cons. Please keep in mind that I do not want to alter the access modifier of a variable for testing purposes.
- 通过反射访问组件的私有变量.
在这种情况下,我有一个存储预订的私有类变量:
In that case I have a private class variable which stores a subscription:
component.ts:
private mySubscription: Subscription;
//...
ngOnInit(): void {
this.mySubscription = this.store
.select(mySelector)
.subscribe((value: any) => console.log(value));
}
ngOnDestroy(): void {
this.mySubscription.unsubscribe();
}
component.spec.ts:
spyOn(component['mySubscription'], 'unsubscribe');
component.ngOnDestroy();
expect(component['mySubscription'].unsubscribe).toHaveBeenCalledTimes(1);
优点:
pros:
- 我可以访问我的订阅.
- 我可以测试是否在右侧调用了unsubscribe方法 订阅.
- I can reach mySubscription.
- I can test that the unsubscribe method was invoked on the right subscription.
缺点:
- 我只能通过反思来达成mySubscription,如果可能的话,我想避免这种事情.
- 我像选项1一样为预订创建一个变量,但是没有反射地到达变量,我只是检查了unsubscribe方法是否被调用,而又不知道其来源.
component.ts:与选项1相同
component.spec.ts:
spyOn(Subscription.prototype, 'unsubscribe');
component.ngOnDestroy();
expect(Subscription.prototype.unsubscribe).toHaveBeenCalledTimes(1);
优点:
pros:
- 我可以测试取消订阅方法是否被调用
缺点:
- 我无法测试所调用的unsubscribe方法的来源.
- 我实现了一个辅助函数,该函数对传递的订阅参数调用unsubscribe方法.
subscription.helper.ts:
export class SubscriptionHelper {
static unsubscribeAll(...subscriptions: Subscription[]) {
subscriptions.forEach((subscription: Subscription) => {
subscription.unsubscribe();
});
}
}
component.ts:与选项1相同,但是ngOnDestroy不同:
component.ts: same as in option 1, but ngOnDestroy is different:
ngOnDestroy(): void {
SubscriptionHelper.unsubscribeAll(this.mySubscription);
}
component.spec.ts:
spyOn(SubscriptionHelper, 'unsubscribeAll');
component.ngOnDestroy();
expect(SubscriptionHelper.unsubscribeAll).toHaveBeenCalledTimes(1);
优点:
pros:
- 我可以测试助手函数是否被调用
缺点:
- 我无法测试是否在特定订阅上调用了取消订阅功能.
你们有什么建议?您如何在单元测试中测试清理?
What do you guys suggest? How do you test the cleanup in unit test?
推荐答案
我遇到了完全相同的问题,这是我的解决方案:
I had exactly the same problem, here's my solution:
component.ts:
component.ts:
private subscription: Subscription;
//...
ngOnInit(): void {
this.subscription = this.route.paramMap.subscribe((paramMap: ParamMap) => {
// ...
});
}
ngOnDestroy(): void {
this.subscription.unsubscribe();
}
component.spec.ts:
component.spec.ts:
let dataMock;
let storeMock: Store;
let storeStub: {
select: Function,
dispatch: Function
};
let paramMapMock: ParamMap;
let paramMapSubscription: Subscription;
let paramMapObservable: Observable<ParamMap>;
let activatedRouteMock: ActivatedRoute;
let activatedRouteStub: {
paramMap: Observable<ParamMap>;
};
beforeEach(async(() => {
dataMock = { /* some test data */ };
storeStub = {
select: (fn: Function) => of((id: string) => dataMock),
dispatch: jasmine.createSpy('dispatch')
};
paramMapMock = {
keys: [],
has: jasmine.createSpy('has'),
get: jasmine.createSpy('get'),
getAll: jasmine.createSpy('getAll')
};
paramMapSubscription = new Subscription();
paramMapObservable = new Observable<ParamMap>();
spyOn(paramMapSubscription, 'unsubscribe').and.callThrough();
spyOn(paramMapObservable, 'subscribe').and.callFake((fn: Function): Subscription => {
fn(paramMapMock);
return paramMapSubscription;
});
activatedRouteStub = {
paramMap: paramMapObservable
};
TestBed.configureTestingModule({
// ...
providers: [
{ provide: Store, useValue: storeStub },
{ provide: ActivatedRoute, useValue: activatedRouteStub }
]
})
.compileComponents();
}));
// ...
it('unsubscribes when destoryed', () => {
fixture.detectChanges();
component.ngOnDestroy();
expect(paramMapSubscription.unsubscribe).toHaveBeenCalled();
});
这对我有用,我希望对您也有用!
This works for me, I hope it will for you too !
这篇关于如何对Angular中的退订功能进行单元测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!