如何用JestMock file-saver的saveAs测试DevExtreme导出功能
解决Jest中Mock file-saver saveAs方法的报错问题
问题场景
在为DevExtreme DataGrid的CSV下载方法编写单元测试时,调用以下代码环节出现mock异常:
saveAs(new Blob([buffer], { type: 'application/octet-stream' }), 'DataGrid.csv')
报错信息
(0 , _fileSaver.default) is not a function
业务代码与测试代码
下载函数
const downloadCsv = () => { const workbook = new Workbook() const worksheet = workbook.addWorksheet('Main Sheet') const exportRes = exportDataGrid({ component: state.gridInstance, worksheet: worksheet }) exportRes.then(() => { workbook.csv.writeBuffer().then((buffer) => { saveAs(new Blob([buffer], { type: 'application/octet-stream' }), 'DataGrid.csv') }) }) }
Jest测试文件
import { shallowMount } from '@vue/test-utils' import downloadComp from '@/components/data-grid/downloadComp' jest.mock('devextreme/excel_exporter', () => ({ exportDataGrid: jest.fn( () => new Promise((r) => r({ data: { from: { row: 1, column: 1 }, to: { row: 26, column: 8 } } })) ) })) jest.mock('exceljs', () => { return { Workbook: jest.fn().mockImplementation(() => { return { addWorksheet: () => {}, csv: { workbook: {}, worksheet: null, writeBuffer: jest.fn( () => new Promise((r) => r({ data: { from: { row: 1, column: 1 }, to: { row: 26, column: 8 } } })) ) } } }) } }) jest.mock('file-saver', () => ({ saveAs: jest.fn() })) describe('Download grid', () => { let wrapper beforeEach(() => { wrapper = shallowMount(downloadComp) }) it('method handleDownload', () => { wrapper.vm.downloadCsv() }) })
解决方案
核心问题
file-saver默认采用默认导出而非命名导出,当前mock写法按命名导出处理,导致找不到对应方法。
修正Mock写法
将file-saver的mock改为模拟默认导出:
jest.mock('file-saver', () => ({ default: jest.fn() }))
匹配导入方式
确保业务代码中使用默认导入:
import saveAs from 'file-saver'
如果业务代码用的是命名导入(import { saveAs } from 'file-saver'),需兼容两种导出方式,修改mock如下:
jest.mock('file-saver', () => { const saveAsMock = jest.fn() return { default: saveAsMock, saveAs: saveAsMock } })
处理异步测试逻辑
由于下载函数包含多层Promise,测试时需等待异步操作完成后再断言:
it('method handleDownload', async () => { await wrapper.vm.downloadCsv() const saveAs = require('file-saver').default expect(saveAs).toHaveBeenCalled() })
内容的提问来源于stack exchange,提问作者Denis J
相关产品推荐
相关产品推荐

