【问题标题】:Angular & Jasmine Unit Test change event for input[type="file"]输入 [type="file"] 的 Angular 和 Jasmine 单元测试更改事件
【发布时间】:2019-01-28 22:34:41
【问题描述】:

我正在尝试 100% 的测试覆盖率,但我似乎无法测试这个 onUploadFile 函数中的内容。

html 模板

<input type="file" formControlName="theUpload" id="upload" (change)="onUploadFile($event, i, true)">

filing.ts 文件

onUploadFile(evt: Event, index: number, isReq: boolean = false): void {
  const reader = new FileReader();
  const target = <HTMLInputElement>evt.target;

  if (target.files && target.files.length) {
    const file = target.files[0];
    reader.readAsDataURL(file);
    reader.onload = () => {
      this.getUploadFormGroup(index, isReq).patchValue({
        filename: file.name,
        filetype: file.type,
        value: reader.result.split(',')[1],
        dateUploaded: new Date()
      });

      console.log(
        `getUploadFormArray (${isReq ? 'required' : 'other'} forms)`,
        this.getUploadFormArray(isReq)
      );
    };
  }
}

filing.spec.ts 文件

it('should call onUploadFile when input is changed for required files', () => {
  spyOn(component, 'onUploadFile').and.callThrough();

  const fakeChangeEvent = new Event('change');

  const targ = <HTMLInputElement>de.nativeElement.querySelector('input#upload');
  targ.dispatchEvent(fakeChangeEvent);

  fixture.whenStable().then(() => {
    expect(component.onUploadFile).toHaveBeenCalledWith(fakeChangeEvent, 0, true);
    expect(targ.files.length).toBeGreaterThan(0); //  this is always zero because i can't add to targ.files (readonly FileList)
  });
});

我愿意模拟任何可以模拟的东西,但有人可以告诉我如何测试console.log 函数(要求我在target.files 数组中至少有一项?

【问题讨论】:

    标签: angular typescript unit-testing jasmine


    【解决方案1】:

    让我们遵循分而治之的规则 - 因为单元测试的目的是分别测试组件逻辑的各个部分,所以我会稍微改变组件逻辑以使单元测试更容易.

    您在 onUploadFile 方法中为 onload 设置匿名回调函数,因此无法窥探它。作为权衡 - 您可以重构回调方法:

    export class TestComponent {
      ...
      getLoadCallback(fg: FormGroup, file: File, reader: FileReader): () => void {
        return () => {
          fg.patchValue({
            filename: file.name,
            filetype: file.type,
            value: reader.result.split(',')[1],
            dateUploaded: new Date()
          });
    
          // do some other stuff here
        };
      }
    
      onUploadFile(evt: Event, index: number, isReq: boolean = false): void {
        const reader = new FileReader();
        const target = <HTMLInputElement>evt.target;
    
        if (target.files && target.files.length) {
          const file = target.files[0];
          reader.readAsDataURL(file);
          const fg = this.getUploadFormGroup(index, isReq);
          reader.onload = this.getLoadCallback(fg, file, reader);
        }
      }
      ...
    }
    

    所以,现在我们可以创建至少三个单元测试:一个用于在输入事件上触发onUploadFile(您现有的测试对此很有用),另一个用于测试getLoadCallback 方法,最后一个用于onUploadFile 方法:

      it('getLoadCallback', () => {
        const mockValue = ['a', 'b'];
        const result = jasmine.createSpyObj('result', ['split']);
        result.split.and.callFake(() => mockValue);
        const mockReader = { result } as FileReader;
        const mockFormGroup: FormGroup = jasmine.createSpyObj('FormGroup', ['patchValue']);
        const mockFile = new File([''], 'filename', { type: 'text/html' });
        const callback: () => void = component.getLoadCallback(mockFormGroup, mockFile, mockReader);
    
        callback();
    
        const obj = {
          filename: mockFile.name,
          filetype: mockFile.type,
          value: mockValue[1],
          dateUploaded: new Date()
        }
        expect(mockFormGroup.patchValue).toHaveBeenCalledWith(obj);
      });
    
      it('onUploadFile', () => {
        const mockIndex = 1;
        const mockIsReq = false;
        const mockFile = new File([''], 'filename', { type: 'text/html' });
        const mockFormGroup = new FormGroup({});
        const mockEvt = { target: { files: [mockFile] } };
        const mockReader: FileReader = jasmine.createSpyObj('FileReader', ['readAsDataURL', 'onload']);
        spyOn(window as any, 'FileReader').and.returnValue(mockReader);
        spyOn(component, 'getUploadFormGroup').and.returnValue(mockFormGroup);
        spyOn(component, 'getLoadCallback').and.callThrough();
    
        component.onUploadFile(mockEvt as any, mockIndex, mockIsReq);
    
        expect((window as any).FileReader).toHaveBeenCalled();
        expect(mockReader.readAsDataURL).toHaveBeenCalledWith(mockFile);
        expect(component.getUploadFormGroup).toHaveBeenCalledWith(mockIndex, mockIsReq);
        expect(component.getLoadCallback).toHaveBeenCalledWith(mockFormGroup, mockFile, mockReader);
      });
    

    当然,您可以更改模拟值并创建更多单元测试...

    【讨论】:

    猜你喜欢
    • 2017-04-04
    • 1970-01-01
    • 1970-01-01
    • 2014-09-25
    • 2017-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多