我已经为此功能编写了单元测试:
getCarsAndSetup(){
this.getCars();
this.getFactoryInfo();
}
这是getCars()函数:
getCars() {
const subscription = this.carDetailsService.getAll().subscribe((carDetails) => {
this.carInfoService.setCars(carDetails);
subscription.unsubscribe(); <-------------- Here the
subscription is undefined
when running the test,
however when running
the app, the subscription
is defined and
everything is fine
});
}
这是单元测试:
fdescribe('getCarsAndSetup', () => {
it('should get cars and set them up', () => {
component.getFactoriesAndUnsubscribe();
spyOn(component, "getCars");
spyOn(component, "getFactoryInfo");
expect(component.getCars).toHaveBeenCalled();
expect(component.getFactoryInfo).toHaveBeenCalled();
});
});
我正在为carDetailsService使用模拟。这是carDetailsService模拟中的getAll()方法:
getAll(): Observable<CarModel[]> {
return Observable.create((observer:any) => {
observer.next([]);
});
}
这与REAL carDetailsService中的方法相同:
getAll(): Observable<CarModel[]> {
return this.http.get<CarModel[]>(this.carUrl);
}
问题是,当我运行应用程序本身时,定义了getCars()方法中的订阅,可以取消订阅等,一切都很好。
但是,当我运行测试时,该测试失败,因为由于某些原因,当我尝试取消订阅时,getCars()函数中的订阅未定义。
仅在运行测试时未定义订阅的原因可能是什么?它可以与我模拟carDetailsService的getAll()函数的方式有关吗?
这里的问题是,您依赖于源Observable的同步/异步行为。
在您的真实应用中,您this.carDetailsService.getAll()
是一个真实的远程调用(异步),因此已将其订阅分配给它,subscription
并且一切正常。但是,在您的测试中,相同的调用可能是模拟的,因此是同步的,因此在您要调用subscription.unsubscribe()
它的时候它仍然是静止的undefined
(该subscribe
方法仍在执行并且尚未返回任何预订)。
您最容易做的是改为传递箭头函数以subscribe
使用function
关键字。RxJS将this
订户处理程序内部的内容绑定到其内部的Subscription对象(我知道这有点棘手,但是打算以这种方式使用)。
const that = this;
this.carDetailsService.getAll().subscribe(function(carDetails) { // note the `function` keyword
that.carInfoService.setCars(carDetails);
this.unsubscribe();
});
另一种方法可能是takeUntil
与Subject一起使用,并在您的计算机中完成它subscribe
。
此行为将来可能会更改:https : //github.com/ReactiveX/rxjs/issues/3983
在不同用例中的相同问题:RxJs:计算组件中的可观察数组长度
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句