You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Vitest中用Vue Test Utils模拟input[type=file]文件选择

解决Vitest中模拟input[type=file]文件选择时的files属性赋值错误问题

问题出在input[type=file]的files属性是只读属性,无法直接通过赋值语句修改,所以原代码中await fileInput.element.files = [mockFile]会抛出属性无效的错误。

以下是两种可行的修正方案:

方案1:使用DataTransfer模拟文件列表

这是更贴近真实浏览器行为的方式,通过DataTransfer对象创建合法的文件列表:

import { mount } from '@vue/test-utils';
it('simulates file selection', async () => {
  const wrapper = mount(MyComponent);
  const fileInput = wrapper.find('input[type="file"]');
  const mockFile = new File(['content'], 'filename.txt', { type: 'text/plain' });

  // 创建DataTransfer并添加模拟文件
  const dataTransfer = new DataTransfer();
  dataTransfer.items.add(mockFile);
  // 将DataTransfer的文件列表赋值给input元素
  fileInput.element.files = dataTransfer.files;

  await fileInput.trigger('change');

  // 验证组件行为
  expect(wrapper.emitted('fileSelected')).toBeTruthy();
});

方案2:通过Object.defineProperty修改只读属性

如果环境不支持DataTransfer(极少情况),可以通过Object.defineProperty强制覆盖files属性:

import { mount } from '@vue/test-utils';
it('simulates file selection', async () => {
  const wrapper = mount(MyComponent);
  const fileInput = wrapper.find('input[type="file"]');
  const mockFile = new File(['content'], 'filename.txt', { type: 'text/plain' });

  // 覆盖只读的files属性
  Object.defineProperty(fileInput.element, 'files', {
    value: [mockFile],
    configurable: true // 允许后续修改或删除该属性
  });

  await fileInput.trigger('change');

  expect(wrapper.emitted('fileSelected')).toBeTruthy();
});

关键说明

  • 两种方案都需要在修改files属性后触发change事件,才能让组件感知到文件选择的变化。
  • 优先使用方案1,因为它完全模拟了浏览器中用户选择文件的真实流程,测试结果更可靠。

内容的提问来源于stack exchange,提问作者Kartik Kodag

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 09:34:54