如何用Jasmine测试URL调用并验证Promise返回值?
如何用Jasmine正确测试Angular的getImageBlob方法
你的原方法实现
getImageBlob(docLink: string): Promise<Blob> { const httpHeaders = new HttpHeaders({ 'TOKEN': token, 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'GET, HEAD, OPTIONS', }); return this.http.get<Blob>(docLink, { headers: httpHeaders, responseType: 'blob' as 'json' }).toPromise(); }
原测试代码的问题
你写的测试存在几个明显问题:
- 错误地在
catch中断言错误状态为200,200是成功状态,不会进入catch分支 - 没有验证HTTP请求是否真的调用了指定URL
- 未正确处理Promise的异步逻辑,可能导致测试在断言执行前就结束,断言不生效
正确的测试方案
下面是完整的测试示例,包含验证URL调用和验证Promise返回值两部分逻辑,使用Angular官方的HttpClientTestingModule来mock HTTP请求:
import { TestBed } from '@angular/core/testing'; import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; // 导入你的服务类和TokenService依赖 describe('你的服务类名称', () => { let service: 你的服务类名称; let httpTestingController: HttpTestingController; const mockImageLink = 'https://example.com/test-image.png'; const mockToken = 'xyzToken'; beforeEach(() => { TestBed.configureTestingModule({ imports: [HttpClientTestingModule], providers: [ 你的服务类名称, // Mock TokenService,返回预设的token { provide: TokenService, useValue: { getToken: () => mockToken } } ] }); service = TestBed.inject(你的服务类名称); httpTestingController = TestBed.inject(HttpTestingController); }); // 每次测试后验证没有未处理的HTTP请求,避免泄漏 afterEach(() => { httpTestingController.verify(); }); // 测试:是否调用了指定的URL和正确的请求方法、请求头 it('should send GET request to the specified URL with correct headers', () => { service.getImageBlob(mockImageLink); // 捕获匹配mockImageLink的HTTP请求 const req = httpTestingController.expectOne(mockImageLink); // 验证请求方法是GET expect(req.request.method).toBe('GET'); // 验证请求头包含正确的TOKEN expect(req.request.headers.get('TOKEN')).toBe(mockToken); }); // 测试:请求成功时是否返回正确的Blob it('should return a Blob when request succeeds', async () => { // 创建测试用的Blob const mockBlob = new Blob(['fake image content'], { type: 'image/png' }); // 调用方法,获取Promise对象 const resultPromise = service.getImageBlob(mockImageLink); // 匹配请求并返回模拟的Blob响应 const req = httpTestingController.expectOne(mockImageLink); req.flush(mockBlob); // 等待Promise完成,验证返回值 const returnedBlob = await resultPromise; expect(returnedBlob instanceof Blob).toBe(true); expect(returnedBlob.type).toBe('image/png'); // 可选:验证Blob内容 const blobText = await returnedBlob.text(); expect(blobText).toBe('fake image content'); }); // 测试:请求失败时是否正确抛出错误 it('should reject with error when request fails', async () => { const mockError = { status: 404, statusText: 'Not Found' }; const resultPromise = service.getImageBlob(mockImageLink); // 匹配请求并返回模拟错误 const req = httpTestingController.expectOne(mockImageLink); req.error(new ErrorEvent('Request failed'), mockError); // 验证Promise被拒绝且错误状态正确 try { await resultPromise; fail('Expected promise to be rejected'); } catch (err) { expect(err.status).toBe(404); expect(err.statusText).toBe('Not Found'); } // 也可以用Jasmine的expectAsync简化 // await expectAsync(resultPromise).toBeRejectedWithError('Not Found'); }); });
关键注意事项
- 用
HttpClientTestingModule来mock HTTP请求,HttpTestingController可以捕获并验证请求的细节 - 使用
async/await处理Promise的异步逻辑,确保断言在Promise完成后执行 expectOne方法可以精准匹配目标URL,确保请求调用了正确的地址- 每次测试后用
verify()检查是否有未处理的请求,避免测试污染 - 分别测试成功、失败两种场景,覆盖完整逻辑
内容的提问来源于stack exchange,提问作者user2436956
相关产品推荐
相关产品推荐

