Bal*_*ács 9 unit-testing subscription observable rxjs angular
我想找到一种方法来测试订阅和主题上的取消订阅功能调用.
我想出了一些可能的解决方案,但每一个都有利有弊.请记住,我不想为了测试目的而改变变量的访问修饰符.
在这种情况下,我有一个私有类变量存储订阅:
component.ts:
private mySubscription: Subscription;
//...
ngOnInit(): void {
this.mySubscription = this.store
.select(mySelector)
.subscribe((value: any) => console.log(value));
}
ngOnDestroy(): void {
this.mySubscription.unsubscribe();
}
Run Code Online (Sandbox Code Playgroud)
component.spec.ts:
spyOn(component['mySubscription'], 'unsubscribe');
component.ngOnDestroy();
expect(component['mySubscription'].unsubscribe).toHaveBeenCalledTimes(1);
Run Code Online (Sandbox Code Playgroud)
优点:
缺点:
component.ts:与选项1相同
component.spec.ts:
spyOn(Subscription.prototype, 'unsubscribe');
component.ngOnDestroy();
expect(Subscription.prototype.unsubscribe).toHaveBeenCalledTimes(1);
Run Code Online (Sandbox Code Playgroud)
优点:
缺点:
subscription.helper.ts:
export class SubscriptionHelper {
static unsubscribeAll(...subscriptions: Subscription[]) {
subscriptions.forEach((subscription: Subscription) => {
subscription.unsubscribe();
});
}
}
Run Code Online (Sandbox Code Playgroud)
component.ts:与选项1中的相同,但ngOnDestroy是不同的:
ngOnDestroy(): void {
SubscriptionHelper.unsubscribeAll(this.mySubscription);
}
Run Code Online (Sandbox Code Playgroud)
component.spec.ts:
spyOn(SubscriptionHelper, 'unsubscribeAll');
component.ngOnDestroy();
expect(SubscriptionHelper.unsubscribeAll).toHaveBeenCalledTimes(1);
Run Code Online (Sandbox Code Playgroud)
优点:
缺点:
你们有什么建议?你如何在单元测试中测试清理?
eth*_*far 11
我遇到了完全相同的问题,这是我的解决方案:
组件.ts:
private subscription: Subscription;
//...
ngOnInit(): void {
this.subscription = this.route.paramMap.subscribe((paramMap: ParamMap) => {
// ...
});
}
ngOnDestroy(): void {
this.subscription.unsubscribe();
}
Run Code Online (Sandbox Code Playgroud)
组件.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();
});
Run Code Online (Sandbox Code Playgroud)
这对我有用,我希望它也适用于你!
Ric*_*ira 10
我想出了一个办法让它发挥作用。
首先,我不会为每个订阅创建一个订阅实例,我通常只使用一个订阅实例,并通过使用实现拆解逻辑并允许子订阅的方法“add”添加到所需的多个订阅中。
private subscriptions: Subscription;
//...
ngOnInit(): void {
this.mySubscription.add(
this.store
.select(mySelector)
.subscribe((value: any) => console.log(value))
);
}
ngOnDestroy(): void {
this.subscriptions.unsubscribe();
}
Run Code Online (Sandbox Code Playgroud)
通过这样做,在我的测试中,我可以依赖订阅原型并检测取消订阅方法调用。在这种情况下,在我调用 ngOnDestroy 之后。
const spy = spyOn(Subscription.prototype, 'unsubscribe');
component.ngOnDestroy();
expect(spy).toHaveBeenCalledTimes(1);
Run Code Online (Sandbox Code Playgroud)
这对你来说好看吗?
component.mySubscription = new Subscription();
spyOn(component.mySubscription, 'unsubscribe');
component.ngOnDestroy();
expect(component.mySubscription.unsubscribe).toHaveBeenCalledTimes(1);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4219 次 |
| 最近记录: |