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

如何使用Vitest和Vue Test Utils测试Vuetify 3的v-select组件?

问题:测试Vuetify v-select组件失败(Vitest + Vue Test Utils)

我在表单中使用了一个v-select组件,组件代码如下:

<v-select
  clearable
  :items="models"
  item-value="id"
  item-text="name"
  ref="model-select"
  required="true"
  v-model="selectedModel"
></v-select>

我尝试了两种测试方法,注释部分为第一种,未注释部分为第二种:

test('it fills the form', async () => {
    models = [
      {
        id: '1',
        name: 'foo',
      },
      {
        id: '2',
        name: 'bar',
      },
    ];
    await nextTick();
    // const select = wrapper?.findComponent({ref: 'model-select'});
    // expect(select?.exists()).toBeTruthy();
    // select?.vm.selectItem('foo');
    // await nextTick();

    wrapper?.find('[data-testid="model-select"]').trigger('click');
    await nextTick();
    wrapper?.find('.menuable__content__active')?.findAll('.v-list-item')?.at(0)?.trigger('click');
    await nextTick();
  });

但两种方法都无效:

  • 第一种方法:DOM包装器无法识别selectItem方法
  • 第二种方法:找不到Vuetify的选择菜单,包装器为空

求适配Vitest和Vue Test Utils的解决方案。


可行解决方案

方法1:直接操作组件实例的内部方法

findComponent返回的是Vue组件包装器,需要先获取组件的内部Vuetify实例,再调用对应方法。正确做法是通过$refs拿到真实的v-select实例,注意要传入完整的item对象而非文本值:

test('it fills the form via component instance', async () => {
  const models = [
    { id: '1', name: 'foo' },
    { id: '2', name: 'bar' },
  ];
  // 假设组件wrapper已挂载,models已传入
  const selectInstance = wrapper.vm.$refs['model-select'];
  
  // 调用v-select内部方法选择指定项
  await selectInstance.selectItem(models[0]);
  
  // 验证v-model是否更新
  expect(wrapper.vm.selectedModel).toBe('1');
});

方法2:正确模拟菜单展开与选择(DOM操作)

Vuetify的v-select菜单是动态渲染的,直接用nextTick可能无法等待菜单完全渲染,改用waitFor更可靠,同时使用准确的菜单选择器:

import { waitFor } from '@testing-library/vue';

test('it fills the form via DOM interaction', async () => {
  const models = [
    { id: '1', name: 'foo' },
    { id: '2', name: 'bar' },
  ];
  // 点击v-select触发菜单展开
  await wrapper.find('[data-testid="model-select"]').trigger('click');
  
  // 等待菜单渲染完成
  await waitFor(() => {
    expect(wrapper.find('.v-menu__content').exists()).toBe(true);
  });
  
  // 点击第一个选项
  await wrapper.findAll('.v-list-item').at(0).trigger('click');
  
  // 验证选中值
  expect(wrapper.vm.selectedModel).toBe('1');
});

方法3:直接设置v-model(快速验证业务逻辑)

如果不需要测试UI交互流程,仅验证组件业务逻辑,可直接修改v-model值:

test('it updates selectedModel correctly', async () => {
  wrapper.vm.selectedModel = '1';
  await nextTick();
  
  // 验证v-select显示的文本是否正确
  expect(wrapper.find('[data-testid="model-select"]').text()).toContain('foo');
});

注意事项

  • 确保测试环境已正确配置Vuetify,比如在全局测试setup中注册Vuetify组件
  • 优先用waitFor处理异步渲染场景,比nextTick更稳定
  • 调用v-select内部方法时,必须传入完整的item对象,而非item-text对应的字符串

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 20:11:24