如何用Jest对RxJS Observable进行单元测试?遇超时问题
解决Jest测试Observable超时问题
你的测试超时核心原因是使用了done参数但未手动调用它,Jest会一直等待done()触发才结束测试。另外还有两处代码问题会加重这个情况,以下是具体修复方案:
1. 在subscribe中调用done()并处理错误回调
当测试函数声明了done参数时,必须在异步操作完成(成功/失败)时调用done(),否则Jest会超时。同时要补充错误回调,确保出错时也能结束测试:
describe("Api Well Repository", () => { it("should retrieve wells", (done) => { const apiWellRepository = new ApiWellRepository( new InMemoryWellRepository() ); const observable$: Observable<Well[]> = apiWellRepository.retrieveAll(); observable$.subscribe({ next: (wells: Well[]) => { expect(wells).toStrictEqual([ { id: "1", name: "Angola_0", }, ]); done(); // 成功时通知Jest测试结束 }, error: (error) => { done(error); // 失败时传递错误,Jest会标记测试失败 } }); }); });
2. 修正catchError的错误用法
你当前的catchError直接抛出错误,会导致错误跳出Observable流,无法被subscribe的错误回调捕获,进而done()不会被调用。正确做法是返回一个错误Observable:
import { throwError } from 'rxjs'; retrieveAll = (): Observable<Well[]> => from(this.wellRepository.retrieveAssets()).pipe( map((assets: Asset[]) => this.mapper.mapping(assets)), catchError(() => { // 返回错误Observable,让subscribe能捕获到错误 return throwError(() => new Error("Something went wrong")); }) );
3. 更简洁的替代方案:使用firstValueFrom + async/await
放弃done参数,改用RxJS的firstValueFrom将Observable转为Promise,结合Jest的async/await语法,代码更简洁且无需手动管理测试结束:
import { firstValueFrom } from 'rxjs'; describe("Api Well Repository", () => { it("should retrieve wells", async () => { const apiWellRepository = new ApiWellRepository( new InMemoryWellRepository() ); const wells = await firstValueFrom(apiWellRepository.retrieveAll()); expect(wells).toStrictEqual([ { id: "1", name: "Angola_0", }, ]); }); });
内容的提问来源于stack exchange,提问作者L. Baptiste
相关产品推荐
相关产品推荐

