在 RxJs 和 Angular 中测试可观察的 'next' 回调
Test observable 'next' callback in RxJs and Angular
我正在尝试使用 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;
}
)
}
当 methodReturningObservable
后面的 observable 发出值时,我如何测试 testMe
是否正确更新?
我尝试这样做:
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
值来发射我的间谍。
我尝试了 getTestScheduler.flush()
,而不是弹珠部分下的 https://netbasal.com/testing-observables-in-angular-a2dbbfaf5329 所示。
我可以使用这样的弹珠在可观察对象上发出值吗?这在 AngularJS 中非常简单,只需触发一个摘要,但我似乎无法让 Anguar 让我进入下一个可观察对象的回调。
我整理了一个简单的 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()
函数来自 marble 测试库,但对于这样一个简单的函数来说,这太过分了。 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);
});
- 注意需要调用组件函数
- getTestScheduler 的刷新也需要完成。
两项测试现在都在 Stackblitz 中通过。
Angular 中大理石测试的官方文档是 here。
希望对您有所帮助。
我正在尝试使用 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;
}
)
}
当 methodReturningObservable
后面的 observable 发出值时,我如何测试 testMe
是否正确更新?
我尝试这样做:
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
值来发射我的间谍。
我尝试了 getTestScheduler.flush()
,而不是弹珠部分下的 https://netbasal.com/testing-observables-in-angular-a2dbbfaf5329 所示。
我可以使用这样的弹珠在可观察对象上发出值吗?这在 AngularJS 中非常简单,只需触发一个摘要,但我似乎无法让 Anguar 让我进入下一个可观察对象的回调。
我整理了一个简单的 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()
函数来自 marble 测试库,但对于这样一个简单的函数来说,这太过分了。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);
});
- 注意需要调用组件函数
- getTestScheduler 的刷新也需要完成。
两项测试现在都在 Stackblitz 中通过。
Angular 中大理石测试的官方文档是 here。
希望对您有所帮助。