仅当运行Angular Jasmine测试时,未定义对observable的订阅,但在运行应用程序本身时进行了定义

gfels

我已经为此功能编写了单元测试:

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();
    });
  });

我正在为carDetailsS​​ervice使用模拟。这是carDetailsS​​ervice模拟中的getAll()方法:

getAll(): Observable<CarModel[]> {
    return Observable.create((observer:any) => {
        observer.next([]);
    });
}

这与REAL carDetailsS​​ervice中的方法相同:

getAll(): Observable<CarModel[]> {
    return this.http.get<CarModel[]>(this.carUrl);
}

问题是,当我运行应用程序本身时,定义了getCars()方法中的订阅,可以取消订阅等,一切都很好。

但是,当我运行测试时,该测试失败,因为由于某些原因,当我尝试取消订阅时,getCars()函数中的订阅未定义。

仅在运行测试时未定义订阅的原因可能是什么?它可以与我模拟carDetailsS​​ervice的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] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章