如何为img标签onerror触发的函数编写Jasmine单元测试(测试失败排查)
解决Jasmine测试img onerror触发getImageUrl函数的失败问题
你的测试用例核心目标是验证:当图片加载失败时,getImageUrl会尝试其他格式图片,若全部失败则显示默认图片assets/img/user-icon.jpg。但现有测试存在几个关键问题导致失败,我们一步步修正:
原测试的问题分析
- 未手动触发img的error事件:在Angular测试环境中,即使设置无效图片URL,浏览器也不会真正发起图片请求,因此
(error)事件不会自动触发,getImageUrl根本没执行。 - 未mock依赖与异步方法:
getImageUrl依赖_appSettingsService获取扩展名列表,还调用了checkImage发起异步请求,未mock这些会导致测试不可控、异步操作未正确等待。 - 异步处理不精准:盲目的
tick(3000)不能保证所有异步操作完成,应该用flush()或精准tick等待微任务。
修正后的测试用例
第一步:提前准备mock与依赖注入
首先在测试套件的beforeEach中mock_appSettingsService,并确保组件依赖正确注入:
import { fakeAsync, flush, ComponentFixture, TestBed } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { YourComponent } from './your-component.component'; import { AppSettingsService } from './path-to/app-settings.service'; import { Observable } from 'rxjs'; // 模拟AppSettingsService const mockAppSettingsService = { appSettings: { probableGxcImageExtensions: ['.png', '.jpeg'] // 模拟扩展名列表 } }; describe('YourComponent', () => { let component: YourComponent; let fixture: ComponentFixture<YourComponent>; let appSettingsService: AppSettingsService; beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [YourComponent], providers: [ { provide: AppSettingsService, useValue: mockAppSettingsService } ] }).compileComponents(); }); beforeEach(() => { fixture = TestBed.createComponent(YourComponent); component = fixture.componentInstance; appSettingsService = TestBed.inject(AppSettingsService); fixture.detectChanges(); });
第二步:编写修正后的测试用例
it('should display default image if all probable image URLs fail', fakeAsync(() => { // 1. 设置测试数据 component.resultsItem = MOCK_RESULTSET.results[9]; component.resultsItem.imageUrl = "https://domain/gxc3/files/Employee_Images/Test.jpg"; fixture.detectChanges(); // 2. 获取img元素并mock checkImage方法,让所有格式检查都返回false spyOn(component, 'checkImage').and.returnValue(Observable.of(false)); // 3. 获取img元素并手动触发error事件(关键!) const imgEl = fixture.debugElement.query(By.css('.item-person-type')).nativeElement; imgEl.dispatchEvent(new Event('error')); fixture.detectChanges(); // 4. 等待所有异步操作完成 flush(); fixture.detectChanges(); // 5. 断言最终src为默认图片 expect(imgEl.getAttribute('src')).toBe('assets/img/user-icon.jpg'); }));
关键细节解释
- 手动触发error事件:通过
dispatchEvent(new Event('error'))强制触发img的error回调,确保getImageUrl执行。 - mock checkImage:用
spyOn让checkImage返回Observable.of(false),模拟所有格式的图片都加载失败的场景,确保最终走到默认图片逻辑。 - flush()替代盲目的tick:
flush()会清空所有待处理的微任务和宏任务,确保forkJoin的subscribe回调完全执行完毕后再断言。
如果还想测试“某个格式图片存在”的场景,只需修改checkImage的返回值:
// 模拟第一个格式(.png)的图片存在 spyOn(component, 'checkImage').and.callFake((src) => { return src.endsWith('.png') ? Observable.of(true) : Observable.of(false); }); // 最终断言src为替换后的png链接 expect(imgEl.getAttribute('src')).toBe('https://domain/gxc3/files/Employee_Images/Test.png');
内容的提问来源于stack exchange,提问作者Sourabh Gupta
相关产品推荐
相关产品推荐

