5

我正在尝试使用 RxJs Observables 在 Angular 中做一个非常简单的测试,但我做不到。这就是我基本上要测试的内容:

// We're inside some Angular component here...
let testMe = 0;

function somethingOrOther(): void {

    this.someService.methodReturningObservable()
      .subscribe(
          (nextValue: number): void => {
              testMe += nextValue;
          }
      ) 
}

当后面的可观察对象发出一个值testMe时,我如何测试它是否正确更新?methodReturningObservable

我用这个尝试过:

it(`works 'cuz I want it to`, fakeAsync(() => {
    spyOn(this.someService, 'methodReturningObservable').and.returnValue(cold('a', {a: 10}));

    tick();

    expect(component.testMe).toBe(10);
}));

所以,tick()这里似乎没有做任何事情。没有什么能让我cold对我的间谍产生任何价值。

我尝试了,如大理石部分下的https://netbasal.com/testing-observables-in-angular-a2dbbfaf5329getTestScheduler.flush()所示。

我可以使用这样的弹珠在可观察对象上发出值吗?只需触发摘要,这在 AngularJS 中非常容易,但我似乎无法让 Anguar 让我进入下一个可观察对象的回调。

4

1 回答 1

3

我整理了一个简单的Stackblitz来向您展示我将如何测试您描述的那个简单的组件方法。

这是 Stackblitz 的规范:

it(`works with "of" 'cuz I want it to`, () => {
    spyOn(someService, 'methodReturningObservable').and.returnValue(of(10));
    component.somethingOrOther();
    expect(component.testMe).toBe(10);
});

我对您的代码所做的一些更改:

  • 我必须对您的组件方法进行微小的更改才能使其正常工作。Stackblitz 中的详细信息。
  • cold()函数来自大理石测试库,但对于这样一个简单的函数来说,这太过分了。rxjsof可用的 Observable 创建方法,它可以创建一个可以订阅的冷同步 observable(但如果你真的想用这种方式测试它,下面会更多)。
  • 由于上面的规范使用了同步的 observable,所以不需要fakeAsync(),因为它会立即完成。
  • 被测方法需要显式调用才能进行测试,上面用 . 行完成component.somethingOrOther()

正如您在 Stackblitz 中看到的,这个测试通过就好了。

现在,如果你想在这个简单的案例中使用大理石测试,我在 Stackblitz 中为此设置了另一个规范。如下:

it(`works with "cold" 'cuz I want it to`, () => {
    spyOn(someService, 'methodReturningObservable').and.returnValue(cold('a', { a: 10 }));
    component.somethingOrOther();
    getTestScheduler().flush(); // flush the observables
    expect(component.testMe).toBe(10);
});
  • 请注意需要调用组件函数的事实
  • getTestScheduler 的刷新也需要完成。

这两项测试现在都通过了 Stackblitz。

Angular 中大理石测试的官方文档在这里

我希望这有帮助。

于 2018-12-14T03:55:07.843 回答