You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为img标签onerror触发的函数编写Jasmine单元测试(测试失败排查)

解决Jasmine测试img onerror触发getImageUrl函数的失败问题

你的测试用例核心目标是验证:当图片加载失败时,getImageUrl会尝试其他格式图片,若全部失败则显示默认图片assets/img/user-icon.jpg。但现有测试存在几个关键问题导致失败,我们一步步修正:

原测试的问题分析

  1. 未手动触发img的error事件:在Angular测试环境中,即使设置无效图片URL,浏览器也不会真正发起图片请求,因此(error)事件不会自动触发,getImageUrl根本没执行。
  2. 未mock依赖与异步方法:getImageUrl依赖_appSettingsService获取扩展名列表,还调用了checkImage发起异步请求,未mock这些会导致测试不可控、异步操作未正确等待。
  3. 异步处理不精准:盲目的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:30:10