在 RxJs 和 Angular 中测试可观察的“下一个”回调

Spe*_*cer 5 rxjs angular jasmine-marbles rxjs-marbles

我正在尝试使用 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;
          }
      ) 
}
Run Code Online (Sandbox Code Playgroud)

testMe当后面的 observablemethodReturningObservable发出值时,如何测试是否正确更新?

我用这个尝试过:

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

    tick();

    expect(component.testMe).toBe(10);
}));
Run Code Online (Sandbox Code Playgroud)

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

我尝试了getTestScheduler.flush(),如弹珠部分下的https://netbasal.com/testing-observables-in-angular-a2dbbfaf5329所示。

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

dmc*_*dle 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);
});
Run Code Online (Sandbox Code Playgroud)

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

  • 我必须对您的组件方法进行一些微小的更改才能使其正常工作。Stackblitz 中的详细信息。
  • cold()函数来自大理石测试库,但这对于如此简单的函数来说有点过大了。rxjs具有of可用的 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);
});
Run Code Online (Sandbox Code Playgroud)
  • 请注意,需要调用组件函数
  • getTestScheduler 的刷新也需要完成。

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

Angular 中大理石测试的官方文档位于此处

我希望这有帮助。