如何用玩笑嘲笑FileReader?

时间:2019-10-10 22:20:41

标签: javascript reactjs unit-testing jestjs filereader

在过去的两周里,我一直在努力地对文件上传react组件进行单元测试。具体来说,我正在尝试测试是否在我的一种方法中从FileReader调用了方法onReadAsDataUrl。这是我正在测试的示例方法:

loadFinalImage = async (file) => {
  const reader = new FileReader();
  reader.onloadend = () => {
    this.setState({
      imagePreviewUrl: reader.result,
      validCard: true,
    });
  };
  await reader.readAsDataURL(file);
}

这是我尝试模拟FileReader并测试是否已调用onReadAsDataUrl的方式:

it('is a valid image and reader.onReadAsDataUrl was called', () => {
    const file = new Blob(['a'.repeat(1)], { type: 'image/png' });
    wrapper = shallow(<ImageUpload />).dive();
    const wrapperInstance = wrapper.instance();
    const mockReader = jest.fn();
    jest.spyOn('FileReader', () => jest.fn());
    FileReader.mockImplementation(() => { return mockReader });
    const onReadAsDataUrl = jest.spyOn(mockReader, 'readAsDataURL');
    wrapperInstance.loadFinalImage(file);
    expect(onReadAsDataUrl).toHaveBeenCalled();
  });

运行:yarn jest后,出现以下测试失败:

  

无法对原始值进行spyOn;给出的字符串。

我认为我收到此错误是因为我没有导入FileReader,但是由于FileReader是一个接口,因此我不确定如何导入或模拟它。这是测试失败的图像: enter image description here

我对Jest,reactjs和Web开发有点菜鸟,但是很想学习如何解决这个问题。到目前为止,我看过的一些资源是:Unresolved Shopify Mock of FileReaderHow to mock a new function in jestMocking FileReader with jasmine

任何帮助将不胜感激!预先谢谢你。

2 个答案:

答案 0 :(得分:2)

我个人无法使用任何jest.spyOn()方法。

使用jest.spyOn(FileReader.prototype, 'readAsDataURL')继续产生Cannot spy the readAsDataURL property because it is not a function; undefined given instead错误,

jest.spyOn(global, "FileReader").mockImplementation(...)返回了Cannot spy the FileReader 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)

我希望它可以帮助其他人对此进行调查。

答案 1 :(得分:0)

到目前为止,OP很可能已经找到了答案,但是由于我面临着几乎相同的问题,这就是我的处理方式-从another SO answer获取输入。

我认为@Jackyef评论是正确的做法,但我认为您建议的致电mockImplementation并不正确。

在我看来,以下内容是正确的。

const readAsDataURL = jest
  .spyOn(global, "FileReader")
  .mockImplementation(function() {
    this.readAsDataURL = jest.fn();
  });

值得一提的是,VSCode强调了匿名函数的潜在重构。它表明:

class (Anonymous function)
(local function)(): void
This constructor function may be converted to a class declaration.ts(80002)

我对JS还是一个新手,所以我担心我无法解释这是什么意思,也无法进行重构。