如何模拟和检查 Jest 框架中库中的函数?

How to mock and check that a function from a library in Jest framework?

我在 ReactJS 代码中定义了一个带有“下载”文本的按钮。现在,我想编写一个单元测试来检查单击此按钮时是否调用了此函数。我写了一个单元测试,但它不起作用。

import * as FileSaver from "file-saver"
  it('File has to be saved when clicked on the "Download" button', () => {
    jest.mock('file-saver', ()=>({saveAs: jest.fn()}));
    fireEvent.click(component.getByText("Download"));
    expect(FileSaver.saveAs).toBeCalled();
  })

我收到此错误:

Error: expect(received).toBeCalled()
Matcher error: received value must be a mock or spy function
Received has type:  function
Received has value: [Function anonymous]

指向 expect(FileSaver.saveAs).toBeCalled(); 行。

怎么了?

因此,正如我在评论中所述,您必须将 jest.mock('file-saver', ()=>({saveAs: jest.fn()})) 从测试正文移至文件顶部,就在导入下方。其原因实际上在文档 here 中得到了回答,但总结一下:

在您的测试文件中,您正在使用 import 语句,该语句在开始时触发,在任何代码有机会 运行 之前。然后您尝试模拟 file-saver,但它已经通过实际实现导入,而不是模拟。如果您指示 jest 在文件顶部模拟模块,它会自动将 jest.mock 调用提升到模块顶部,因此您的函数 exportToExcel 将接收模拟的 file-saver 而不是正品。

但是,如果出于某种奇怪的原因你真的想在测试主体中模拟 file-saver,则需要模拟 file-saver,然后在测试中包含所有使用 [=13= 的模块],像这样:

it('File has to be saved when clicked on the Export button', () => {
    jest.mock('file-saver', ()=> ({ saveAs: jest.fn() }));
    const component = require('/path/to/tested/componetn/on/which/click/event/is/fired');
    const FileSaver = require('file-saver');

    fireEvent.click(component.getByText("Download"));

    expect(FileSaver.saveAs).toBeCalled();
})