Vue3使用Jest测试文件上传时遇undefined错误的解决方法
解决Jest测试Quasar文件上传组件时的
expect(received).toEqual(expected)异常 问题描述
我尝试用Jest为文件上传和Excel导出功能编写单元测试,在测试文件上传逻辑时遇到了深度相等断言失败的异常,预期值为{},实际值为undefined。
组件代码(Vue + Quasar)
<template> <div class="q-gutter-y-xs row items-start"> <q-card flat style="width: 100%" dense> <Page-Content ref="pageContent" > <template #header> <div class="q-px-md"> <div class="q-gutter-sm row"> <q-item class="col-4 col-sm-12" style="margin-left: 0"> <q-file name="selectuploadfile" standout="bg-blue-1 text-indigo" outlined dense style="width: 270px" v-model="ExcelList" :label="$t('select_upload_file')" > <template v-slot:prepend> <q-icon name="cloud_upload" @click.stop /> </template> <template v-slot:append> <q-icon name="close" @click.stop="ExcelList = null" class="cursor-pointer" /> </template> </q-file> <q-btn :label="$t('upload')" @click="importExcel" /> <q-btn :label="$t('upload_sample')" href="./UploadSample/AverageYearsDataDefine.xlsx" /> <q-btn :label="$t('export_to_excel')" @click="exportExcel" /> </q-item> </div> </div> </template> </Page-Content> </q-card> </div> </template>
测试代码
describe('AverageYearsDataDefine', () => { it('fill up form', async () => { const file = new File(['test file'], 'test.xlsx', { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', }); const fileInput = wrapper.get('[name="selectuploadfile"]'); await fileInput.trigger('change', file); expect(wrapper.vm.ExcelList).toEqual(file); }); });
错误信息
expect(received).toEqual(expected) // deep equality
预期值:{}
实际值:undefined
解决方案
1. 定位Quasar q-file内部的原生input元素
Quasar的q-file是封装后的组件,直接触发组件本身的change事件无效,必须找到其内部的原生<input type="file">元素:
// 方法1:通过组件名称查找 const qFileComponent = wrapper.findComponent({ name: 'QFile' }); const nativeInput = qFileComponent.find('input[type="file"]'); // 方法2:通过属性查找内部input const nativeInput = wrapper.find('[name="selectuploadfile"] input[type="file"]');
2. 构造符合规范的FileList对象
原生文件输入框的change事件中,target.files是FileList类型,而非单个File对象,需要手动构造:
const file = new File(['test file'], 'test.xlsx', { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', }); // 构造FileList const fileList = Object.assign(new FileList(), { 0: file, length: 1 });
3. 正确触发事件并等待组件更新
触发原生input的change事件时,需要传递包含files属性的事件对象,并等待Vue完成响应式更新:
await nativeInput.trigger('change', { target: { files: fileList } }); // 等待组件更新 await wrapper.vm.$nextTick();
4. 确保组件数据正确声明
确认组件的ExcelList是在data中声明的响应式数据:
export default { data() { return { ExcelList: null }; }, // ...其他方法 };
修改后的测试代码
describe('AverageYearsDataDefine', () => { it('fill up form', async () => { const file = new File(['test file'], 'test.xlsx', { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', }); const fileList = Object.assign(new FileList(), { 0: file, length: 1 }); // 找到原生input const qFileComponent = wrapper.findComponent({ name: 'QFile' }); const nativeInput = qFileComponent.find('input[type="file"]'); // 触发事件并等待更新 await nativeInput.trigger('change', { target: { files: fileList } }); await wrapper.vm.$nextTick(); expect(wrapper.vm.ExcelList).toEqual(file); }); });
内容的提问来源于stack exchange,提问作者mamoru1314
相关产品推荐
相关产品推荐

