Jest测试中retryWhen未多次触发getUser调用的问题排查
问题原因分析
你遇到的核心问题是**retryWhen的工作机制理解偏差**:
- 当
myService.getUser返回的Observable抛出错误后,这个Observable就会终止。retryWhen操作符是监听上游的错误流,但它不会自动重新触发myService.getUser的调用——除非上游Observable被重新订阅。 - 你当前的代码中,上游Observable只被订阅了一次,所以
myService.getUser只会执行一次,后续retryWhen只是在错误流上重复处理,并不会再次调用原方法。
另外你的业务代码还有两个小问题:
map里的return { data: data };中data未定义,应该是resultretryWhen的终止条件逻辑错误:retryCount++ ===10会在第11次尝试时才抛出错误,实际重试次数会是10次,总调用次数为11次(初始1次+10次重试)
解决方案
1. 修正业务代码:用defer确保每次重试都重新调用getUser
使用rxjs的defer操作符包装myService.getUser,这样每次订阅(包括重试时的重新订阅)都会执行一次myService.getUser():
import { defer } from 'rxjs'; public getUser(userId: number, delayTime): Observable<any> { // 用defer包装,确保每次订阅都重新执行getUser调用 return defer(() => this.myService.getUser(userId)).pipe( map((result: any) => { if (result) { return { data: result }; // 修正data未定义的问题 } throw new Error('Result is empty'); }), retryWhen((errors) => { let retryCount = 0; return errors.pipe( delay(delayTime), tap(() => { retryCount++; // 当重试次数达到10次时,抛出错误终止重试 if (retryCount >= 10) { throw new Error('Max retries exceeded'); } }), ); }), ); }
2. 修正测试代码:处理错误回调并验证调用次数
原测试只监听了next回调,但最终会抛出错误,需要添加error回调来完成断言,同时注意总调用次数是11次(初始1次+10次重试):
it('getUser throws error, getUser is called 11 times (1 initial + 10 retries)', (done) => { // mock service myService.getUser = jest.fn(() => throwError('mock error')); getUser(23, 1).subscribe({ next: () => { // 不会走到这里,因为一直报错 done.fail('Should not emit next value'); }, error: () => { expect(myService.getUser).toHaveBeenCalledTimes(11); done(); } }); });
如果你的项目是Angular或支持fakeAsync,也可以用同步测试方式避免回调嵌套:
import { fakeAsync, tick } from '@angular/core/testing'; it('getUser throws error, getUser is called 11 times', fakeAsync(() => { myService.getUser = jest.fn(() => throwError('mock error')); let errorReceived = false; getUser(23, 100).subscribe({ error: () => errorReceived = true }); // 模拟等待所有重试延迟完成 tick(100 * 10); tick(); // 等待最后一次错误抛出 expect(errorReceived).toBe(true); expect(myService.getUser).toHaveBeenCalledTimes(11); }));
内容的提问来源于stack exchange,提问作者Michael Gee
相关产品推荐
相关产品推荐

