[英]Angular2 / RxJS / Jasmine : How to test Observable chain/sequence (operators)
As part of an Angular 4 project, I am desperately trying to test with Jasmine a function which implement an RxJs chain/sequence with operators ( map
in my case). 作为Angular 4项目的一部分,我正拼命尝试用Jasmine测试一个功能,该功能通过运算符实现RxJs链/序列(在我的情况下为
map
)。
class RendezVousResolver {
searchRendezVous(code: string): Observable<any> {
return Observable.create(observer => {
this.userCardService.readCard(code).map(userData => {
this.rendezVousService.search(userData).subscribe(
result => {
observer.next(result);
},
error => {
observer.error(error);
}
);
});
});
}
}
My unit test uses 2 mocks in order to "simulate" the 2 services' layers: userCardService
and rendezVousService
. 我的单元测试使用2个模拟来“模拟”这2个服务的层:
userCardService
和rendezVousService
。
class MockUserCardService {
readCard(code: string): Observable<any> {
return Observable.of('<data></data>');
}
}
class MockRendezVousService {
search(userData : string): Observable<any> {
return Observable.of({
rdvs: []
});
}
}
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
RendezVousResolver,
{ provide: RendezVousService, useClass: MockRendezVousService },
{ provide: SwcVitaleReadingService, useClass: MockSwcVitaleReadingService }
]
});
fixture = TestBed.get(RendezVousResolver);
});
And here my unit test. 这是我的单元测试。
it('should return the expected response', async(() => {
fixture.resolve(undefined, undefined).subscribe(
rdvs => {
console.log("expect");
expect(rdvs).toEqual({
rdvs: []
});
},
error => {
console.log("fail");
fail('No error was expected');
}
);
}));
When I execute it, the test seems to not wait for the events emitted by the mocked Observable. 当我执行它时,测试似乎没有等待模拟的Observable发出的事件。 Neither the
expected
nor the fail
are executed. 既不执行
expected
fail
,也不执行fail
。 I'm sure about that because nothing is logged in the console. 我敢肯定,因为控制台中没有任何记录。
The only way I found to make this test passed is to not use the operator map
and replace my code with nested subscriptions. 我发现通过此测试的唯一方法是不使用运算符
map
而将我的代码替换为嵌套订阅。
searchRendezVous(code: string): Observable<any> {
return Observable.create(observer => {
this.userCardService.readCard(code).subscribe(
userData => {
this.rendezVousService.search(userData).subscribe(
rdvs => {
observer.next(rdvs);
},
error => {
observer.error(error);
}
)
},
error => {
observer.error(error);
}
);
});
}
I encountered the same problem with others operators than map
( zip
for example). 除
map
(例如zip
)之外,其他运算符也遇到了相同的问题。
Thank you for your help. 谢谢您的帮助。
You can simplify your RendezVousResolver
by swapping Observable.create
for existing behaviour / functions in RxJs: 您可以通过将
Observable.create
交换为RxJs中的现有行为/函数来简化RendezVousResolver
:
class RendezVousResolver {
searchRendezVous(code: string): Observable<any> {
return this.userCardService.readCard(code)
.mergeMap(userData => this.rendezVousService.search(userData));
}
}
That way you have less edge cases to catch yourself. 这样,您就可以减少遇到麻烦的情况。
Testing this can be done without time by swapping the readCard
and search
with mocks returning a Rx.Observable.from([])
with the expected mock data. 这个测试可以不受时间通过交换来完成
readCard
和search
与嘲笑返回Rx.Observable.from([])
与预期的模拟数据。 Simply invoking .toPromise()
on your searchRendezVous()
will make that work without any scheduler magic. 只需在
searchRendezVous()
.toPromise()
上调用.toPromise()
使此工作无需任何调度程序魔术。
it('returns data', () => {
return searchRendezVous('foo')
.toPromise()
.then(searchResults => {
expect(searchResults).to.not.be.empty();//assert what you need
})
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.