【问题标题】:Unit test for uploading a png file上传 png 文件的单元测试
【发布时间】:2021-03-29 01:12:09
【问题描述】:

我是单元测试的初学者,我想测试我的打字稿方法 onSelect,它允许用户仅选择图像、pdf 和 word 文件。这是我的打字稿方法:

 addedfiles : Array<any> = [];
 fileRestrictions: FileRestrictions = {
  allowedExtensions: ['.jpg', '.png', '.jpeg', '.doc', '.docx','.pdf'],
   maxFileSize: 5000000
  };
public onSelect(ev: any): void {
  ev.files.forEach((file: FileInfo) => {
 
  if (file.rawFile) {
    const reader = new FileReader();
    if(this.fileRestrictions.allowedExtensions.includes(file.extension.toLowerCase()))
    {reader.onloadend = () => {
      this.addedfiles.push({ ...file, src: reader.result as string });
    };
    reader.readAsDataURL(file.rawFile);
    console.log(this.addedfiles)
    }
    }
   });
   }

我想编写一个单元测试来测试此方法是否允许用户选择 png 文件。所以我创建了这个单元测试:

it('should select a png file', () => {

  const ev = { prevented : false , files : [{uid : '01', name : 'filename', extension : 'png' 
  , size : 123000 }]};

  component.onSelect(ev);

  expect(component.addedfiles.length).toEqual(1);

})

它给了我错误:Expected 0 to equal 1!谁能帮帮我?

【问题讨论】:

  • 嗨,我看到有人检查了file.rawFile。在单元测试中,您没有该设置。试试这个为ev? const ev = { prevented : false, files : [{uid : '01', name : 'filename', extension : 'png', size : 123000, rawFile: true }]}; 或者更适合 rawFile 的值 :)
  • @user3009269 不,它仍然是同样的问题,PS:当我在我的 onSelect 方法中 console.log(addedfiles) 并选择一个 png 文件时它工作正常并且 addefiles 不为空!所以可能单元测试不正确
  • 我对@9​​87654326@ 不太熟悉,但也许这在您的单元测试中作为rawFile 的模拟值更有意义:data:image/png;base64,AAAFBfj42Pj4
  • Hmmm...我认为问题实际上是文件是在异步方法onloadend中添加的文件中添加的事实...所以您的单元测试在@987654330之前达到了预期功能@回调被执行...

标签: angular typescript unit-testing karma-runner


【解决方案1】:

由于reader.onloadend = () =&gt; {...} 是私有函数,因此无法测试。 你最好使用reader.addEventListener('loadend', () =&gt; {...})。所以我们可以模拟addEventListener 方法。

此外,Array.prototype.includes() 是完全匹配的,您的测试数据extension: 'png' 应该是extension: '.png'。而且,您的测试数据缺少rawFile 属性。

使用angular v11+ 的工作示例:

example.component.ts:

import { Component } from '@angular/core';

type FileRestrictions = any;
type FileInfo = any;

@Component({})
export class ExampleComponent {
  addedfiles: Array<any> = [];
  fileRestrictions: FileRestrictions = {
    allowedExtensions: ['.jpg', '.png', '.jpeg', '.doc', '.docx', '.pdf'],
    maxFileSize: 5000000,
  };
  public onSelect(ev: any): void {
    ev.files.forEach((file: FileInfo) => {
      if (file.rawFile) {
        const reader = new FileReader();
        if (
          this.fileRestrictions.allowedExtensions.includes(
            file.extension.toLowerCase()
          )
        ) {
          console.log(reader);
          reader.addEventListener('loadend', () => {
            this.addedfiles.push({ ...file, src: reader.result as string });
          });
          reader.readAsDataURL(file.rawFile);
          console.log(this.addedfiles);
        }
      }
    });
  }
}

example.component.spec.ts:

import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { ExampleComponent } from './example.component';

fdescribe('65356063', () => {
  let fixture: ComponentFixture<ExampleComponent>;
  let component: ExampleComponent;
  beforeEach(
    waitForAsync(() => {
      TestBed.configureTestingModule({
        declarations: [ExampleComponent],
      })
        .compileComponents()
        .then(() => {
          fixture = TestBed.createComponent(ExampleComponent);
          component = fixture.componentInstance;
        });
    })
  );

  it('should select a png file', () => {
    const ev = {
      prevented: false,
      files: [
        {
          uid: '01',
          name: 'filename',
          extension: '.png',
          size: 123000,
          rawFile: 'test raw file',
        },
      ],
    };

    const mockReader = {
      addEventListener: jasmine.createSpy().and.callFake((event, listener) => {
        listener();
      }),
      readAsDataURL: jasmine.createSpy(),
    };
    spyOn(window, 'FileReader').and.returnValue(
      (mockReader as unknown) as FileReader
    );

    component.onSelect(ev);

    expect(component.addedfiles.length).toEqual(1);
    expect(mockReader.addEventListener).toHaveBeenCalledOnceWith(
      'loadend',
      jasmine.any(Function)
    );
    expect(mockReader.readAsDataURL).toHaveBeenCalledOnceWith('test raw file');
  });
});

测试结果:

【讨论】:

  • 嗨@slideshowp2 感谢您的回答!我有一个编译错误Property 'toHaveBeenCalledOnceWith' does not exist on type 'Matchers&lt;any&gt;'.
  • @hibanebli 你也可以使用toHaveBeenCalled()
  • 它给了我这个错误error TS2345: Argument of type '"FileReader"' is not assignable to parameter of type '"name" | "status" | "location" | "top" | "Blob" | "URL" | "URLSearchParams" | "applicationCache" | "caches" | "clientInformation" | "closed" | "crypto" | "customElements" | "defaultStatus" | ... 221 more ... | "onunload"'. 81 spyOn(window, 'FileReader').and.returnValue(
  • @hibanebli 可以将返回值的类型强制转换为any
  • 非常感谢它现在成功了
猜你喜欢
  • 2013-09-30
  • 1970-01-01
  • 2013-06-11
  • 1970-01-01
  • 1970-01-01
  • 2019-10-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多