【问题标题】:How can I mock FileReader with jest?如何用玩笑模拟 FileReader?
【发布时间】:2020-02-08 10:13:12
【问题描述】:

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

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 后,我得到以下测试失败:

无法窥探原始值;给定的字符串。

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

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

任何帮助将不胜感激!提前谢谢你。

【问题讨论】:

  • 根据文档:jestjs.io/docs/en/jest-object#jestspyonobject-methodname,函数签名是:jest.spyOn(object, methodName) 您是否尝试在 global 中为 FileReader 创建一个模拟,然后改为使用 jest.spyOn(global, 'FileReader')
  • 我将jest.spyOn('FileReader', () =&gt; jest.fn()) 换成了jest.spyOn(global, 'FileReader'),错误信息变成了这一行:FileReader.mockImplementation(() =&gt; { return mockReader })。新的错误信息是:TypeError: _sys.default.mockImplementation is not a function

标签: javascript reactjs unit-testing jestjs filereader


【解决方案1】:

我个人无法使用任何 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)

我希望它可以帮助其他人研究这个。

【讨论】:

    【解决方案2】:

    现在很可能 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 还比较陌生,所以我恐怕无法解释这是什么,也不应该进行什么重构。

    【讨论】:

      猜你喜欢
      • 2021-01-06
      • 1970-01-01
      • 2022-10-06
      • 2020-12-17
      • 2019-04-24
      • 1970-01-01
      • 1970-01-01
      • 2020-10-20
      • 2021-11-27
      相关资源
      最近更新 更多