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

Angular Jasmine测试FileReader提示spy未被调用错误求解

FileReader单元测试报错Expected spy FileReader to have been called.解决方案

问题根因

  • 你在组件类初始化阶段就执行了reader = new FileReader(),而window.FileReader的spy是在it测试用例中才注册的,此时组件已经完成初始化,reader属性已经是真实的FileReader实例,不会触发你spy的构造函数
  • 测试构造的mockEvt结构不符合业务代码要求:业务代码中调用了files.item(0)获取文件,但你构造的files是普通数组,没有item方法,会导致逻辑提前终止
  • Mock的FileReader不会自动触发onload回调,且你没有对parse方法做监听,无法判断回调是否执行

修复后的测试代码

describe('AppComponent', () => {
  let mockFile = new File(['testData'], 'filename.csv', { type: 'text/csv' });
  // 修复mockEvt的files结构,添加item方法
  let mockEvt = { 
    target: { 
      files: Object.assign([mockFile], {
        item: (index: number) => [mockFile][index]
      }) 
    } 
  };
  // onload是属性不是方法,createSpyObj不用传进去
  let mockReader: jasmine.SpyObj<FileReader> = jasmine.createSpyObj('FileReader', ['readAsText']);

  beforeEach(waitForAsync(() => {
    // 要在组件实例化之前就spy FileReader构造函数
    spyOn(window, 'FileReader').and.returnValue(mockReader);
    TestBed.configureTestingModule({
      declarations: [ AppComponent ],
      providers: [],
      imports: [HttpClientTestingModule, BrowserDynamicTestingModule],
    }).compileComponents();
    component = fixture.componentInstance;
    fixture.detectChanges();
    spyOn(component, 'readFileOnChange').and.callThrough();
    // 监听parse方法
    spyOn(component, 'parse').and.callThrough();
  }));

  it('should call parse on onLoad of FileReader', () => {
    component.readFileOnChange(mockEvt as any);
    // 验证构造函数调用
    expect(window.FileReader).toHaveBeenCalled();
    // 验证readAsText调用
    expect(mockReader.readAsText).toHaveBeenCalledWith(mockFile, 'UTF-8');
    // 手动触发onload回调
    mockReader.onload(new ProgressEvent('load'));
    // 验证parse被调用
    expect(component.parse).toHaveBeenCalled();
  });
})

核心修改点说明

  • 调整mockEvt的files结构,添加业务代码依赖的item方法,避免逻辑提前返回
  • 将window.FileReader的spy移到beforeEach中组件实例化之前执行,保证组件初始化时拿到的是Mock的FileReader实例
  • 新增对parse方法的spy监听,用于验证回调逻辑是否执行
  • 手动调用Mock实例的onload方法触发回调,模拟真实FileReader加载完成的行为
  • 修正Mock对象的声明,onload是实例属性不是方法,不需要放到createSpyObj的方法列表中

内容的提问来源于stack exchange,提问作者tiana

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 14:51:04