如何使用玩笑来模拟FileReader

时间:2019-10-31 13:47:05

标签: javascript jestjs

我需要通过玩笑来模拟使用FileReader的函数。 特别是功能readAsBinaryStringonload

我已经创建了一些代码:

FileReader.readAsBinaryString = () => mock.mockReturnValue(null);

但是它不起作用。 如何使用玩笑来模拟FileReader和您的函数?

要测试的功能:

handleFileUpload(event) {
  let reader = new FileReader();
  let file = event.target.files[0];

  reader.readAsBinaryString(file);

  reader.onload = () => {
    let base64String = btoa(reader.result);
    this.object.image = 
  };
},

5 个答案:

答案 0 :(得分:0)

您可以使用jest.spyOn(object, methodName, accessType?)监视readAsBinaryString的{​​{1}}方法。 FileReader是实例方法,不是readAsBinaryString构造函数的静态方法。此外,FileReader的返回值为readAsBinaryString。因此,您不能模拟返回值。

例如

void

index.ts

export function main() { const fr = new FileReader(); const blob = new Blob(); fr.readAsBinaryString(blob); } ,我们需要监视index.spec.ts,因为它是一个实例方法。

FileReader.prototype.readAsBinaryString

覆盖率100%的单元测试结果:

import { main } from './';

describe('main', () => {
  test('should mock FileReader', () => {
    const readAsBinaryStringSpy = jest.spyOn(FileReader.prototype, 'readAsBinaryString');
    main();
    expect(readAsBinaryStringSpy).toBeCalledWith(new Blob());
  });
});

更新

PASS src/stackoverflow/58644737/index.spec.ts main ✓ should mock FileReader (10ms) ----------|----------|----------|----------|----------|-------------------| File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s | ----------|----------|----------|----------|----------|-------------------| All files | 100 | 100 | 100 | 100 | | index.ts | 100 | 100 | 100 | 100 | | ----------|----------|----------|----------|----------|-------------------| Test Suites: 1 passed, 1 total Tests: 1 passed, 1 total Snapshots: 0 total Time: 4.852s, estimated 9s

index.ts

export class Component { object = { image: '' }; handleFileUpload(event) { let reader = new FileReader(); let file = event.target.files[0]; reader.readAsBinaryString(file); reader.onload = () => { let base64String = btoa(reader.result as string); this.object.image = base64String; }; return reader; } }

index.spec.ts

覆盖率100%的单元测试结果:

import { Component } from './';

const cmp = new Component();

describe('main', () => {
  beforeEach(() => {
    jest.restoreAllMocks();
  });
  test('should test handle file upload correctly', () => {
    const mFile = new File(['go'], 'go.pdf');
    const mEvent = { target: { files: [mFile] } };
    const readAsBinaryStringSpy = jest.spyOn(FileReader.prototype, 'readAsBinaryString');
    const btoaSpy = jest.spyOn(window, 'btoa');
    const reader = cmp.handleFileUpload(mEvent);
    expect(reader).toBeInstanceOf(FileReader);
    if (reader.onload) {
      Object.defineProperty(reader, 'result', { value: 'gogo' });
      const mOnloadEvent = {} as any;
      reader.onload(mOnloadEvent);
      expect(btoaSpy).toBeCalledWith('gogo');
      expect(cmp.object.image).toBe(btoa('gogo'));
    }
    expect(readAsBinaryStringSpy).toBeCalledWith(mFile);
  });
});

源代码:https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/58644737

答案 1 :(得分:0)

我已经取得了一些进展:

quad

问题在于在实际通话中不会模拟onload:

const dummy = {
     readAsBinaryString: jest.fn(),
        onload: function(){
          wrapper.vm.object.image = '...'
        }
     }
   }

window.FileReader = jest.fn(() => dummy)

只有当我打电话

reader.onload = function() {
}

所以我认为在哑元上的onload声明是错误的。

答案 2 :(得分:0)

我个人无法在我的Vue-test-utils设置中使用任何jest.spyOn()方法,jest.spyOn(FileReader.prototype, 'readAsDataURL');不断产生以下错误: Cannot spy the readAsDataURL property because it is not a function; undefined given instead

如果它可以帮助其他有此问题的人,我设法使用以下方法成功模拟了FileReader原型:

Object.defineProperty(global, 'FileReader', {
  writable: true,
  value: jest.fn().mockImplementation(() => ({
    readAsDataURL: jest.fn(),
    onLoad: jest.fn()
  })),
})

然后在我的测试中,我可以通过模拟事件并像这样手动触发它来测试文件输入的onChange方法(该方法使用了FileReader):

const file = {
  size: 1000,
  type: "audio/mp3",
  name: "my-file.mp3"
}
const event = {
  target: {
    files: [file]
  }
}
wrapper.vm.onChange(event)

答案 3 :(得分:0)

评论很晚,但值得一提的是,这就是我模拟FileReader的方式:

首先,我创建了一个函数,该函数返回新的FileReader()而不是直接调用它。

export function fileReaderWrapper() {
  return new FileReader();
}

然后需要文件读取器的代码可以调用该函数

const reader = fileReaderWrapper();
reader.readAsDataURL(file);
while (reader.readyState !== 2) {
  yield delay(100);
}
const imageData = reader.result;

现在,我的测试可以使用笑话来模拟我检查的所有内容..而且,我不再需要在测试中使用超时来等待FileReader完成读取文件。

jest.mock('~/utils/helper', () => ({
  fileReaderWrapper: jest.fn().mockReturnValue({
    readAsDataURL: (file: File) => {
      return;
    },
    readyState: 2,
    result: 'data:image/png;base64,undefined',
  }),
}));

答案 4 :(得分:0)

如果要将onload事件作为readAsText的一部分调用,则可以使用以下代码

Company