![](/img/trans.png)
[英]Playwright test will only pass when debugging, but fails when running when testing angular app
[英]Subscription to an observable is undefined only when running Angular Jasmine test, but is defined when running the app itself
我为这个函数写了一个单元测试:
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
use function
关键字。 RxJS结合this
里面用户处理其内部认购对象(我知道这是一个有点棘手的方法,但它打算使用这种方式)。
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: Calculating observable array length in component
虽然马丁的回答确实消除了错误,但它帮助我发现了这里的实际问题,这太愚蠢了。 我在实际的函数调用之后设置了间谍:
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();
});
});
当必须在实际函数调用之前定义间谍时:
fdescribe('getCarsAndSetup', () => {
it('should get cars and set them up', () => {
spyOn(component, "getCars");
spyOn(component, "getFactoryInfo");
component.getFactoriesAndUnsubscribe();
expect(component.getCars).toHaveBeenCalled();
expect(component.getFactoryInfo).toHaveBeenCalled();
});
});
我很难过马丁花了这么多时间在这个答案上并阅读了我发布的长篇描述,结果发现整个问题只是一个小小的疏忽。 但是它就是这样啊。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.