HttpInterceptor单元测试异常:断言结果不符合预期求助
问题原因排查
核心问题
你的测试不管断言写toBeTruthy还是toBeFalsy都能通过,本质是断言根本没被执行。因为RxJS的Observable.subscribe是异步操作,jest默认不会等待异步回调完成,测试代码执行到result.subscribe()后就直接结束了,完全没等到error或next回调里的断言/fail执行。
验证方式
你可以在断言里加个控制台输出验证:
error: (err) => { console.log('断言执行了'); expect(err).toBeFalsy(); }
运行测试会发现这条日志根本不会输出,证明回调从未被触发。
修复方案
下面是几种通用的解决方式,按需选择:
方案1:使用jest的done回调
通过done告诉jest等待异步操作完成:
it.each([500, 501])('should handle 500/501 errors', (statusCode, done) => { const response = new HttpErrorResponse({ status: statusCode }); const request = new HttpRequest('GET', '/fakeUrl'); const mockHandler = { handle: jest.fn(() => throwError(() => response )) }; const result = errorInterceptor.intercept(request, mockHandler); result.subscribe({ next: () => { fail('error should be thrown'); done.fail('next callback should not be called'); }, error: (err) => { expect(err).toBeTruthy(); done(); // 通知jest测试完成 }, complete: () => done.fail('complete callback should not be called') }); });
方案2:用RxJS的firstValueFrom转Promise(RxJS 7+)
利用async/await让jest等待Promise完成:
import { firstValueFrom } from 'rxjs'; it.each([500, 501])('should handle 500/501 errors', async () => { const response = new HttpErrorResponse({ status: statusCode }); const request = new HttpRequest('GET', '/fakeUrl'); const mockHandler = { handle: jest.fn(() => throwError(() => response )) }; const result = errorInterceptor.intercept(request, mockHandler); try { await firstValueFrom(result); fail('error should be thrown'); } catch (err) { expect(err).toBeTruthy(); } });
方案3:使用TestScheduler同步测试(适合复杂场景)
用RxJS的测试调度器把异步操作转为同步执行:
import { TestScheduler } from 'rxjs/testing'; let testScheduler: TestScheduler; beforeEach(() => { errorInterceptor = new ErrorInterceptor(); testScheduler = new TestScheduler((actual, expected) => { expect(actual).toEqual(expected); }); }); it.each([500, 501])('should handle 500/501 errors', (statusCode) => { testScheduler.run((helpers) => { const { cold, expectObservable } = helpers; const response = new HttpErrorResponse({ status: statusCode }); const request = new HttpRequest('GET', '/fakeUrl'); const mockHandler = { handle: jest.fn(() => cold('#', null, response)) }; const result = errorInterceptor.intercept(request, mockHandler); expectObservable(result).toBe('#', null, response); }); });
内容的提问来源于stack exchange,提问作者matt-rock
相关产品推荐
相关产品推荐

