如何使用Jest测试v-calendar组件是否成功渲染
你现在拿到的渲染结果只有<v-calendar>空标签,且属性显示locale="[object Object]",核心原因是测试环境没有正确注册VCalendar组件:Vue无法识别这个自定义组件,只会把它当成普通未知HTML标签渲染,完全不会执行组件内部的渲染逻辑,自然拿不到.vc-container、.vc-pane-container这类v-calendar内部生成的DOM节点,传入的object类型prop也会被直接序列化为HTML属性,转成[object Object]字符串。
另外你的断言写法也有问题:.vc-container是CSS选择器语法,实际HTML的class属性里不会带前缀的.,就算组件正常渲染,匹配字符串.vc-container也会失败。
1. 测试环境正确注册VCalendar插件
根据你用的Vue版本,在mount配置里注册VCalendar,不要让测试环境把v-calendar识别为未知标签:
Vue3 + Vue Test Utils v2 写法
import { mount } from '@vue/test-utils' import VCalendar from 'v-calendar' import 'v-calendar/dist/style.css' import Calendar from './template.vue' test('v-calendar 正常渲染', async () => { const wrapper = mount(Calendar, { global: { plugins: [VCalendar] // 注册插件 } }) await wrapper.setData({ locale: { id: 'en' }, attrs: [{ key: 'today', highlight: { class: 'date-circle', contentClass: 'date-text', }, dates: new Date(), }], }) // 等待异步渲染完成 await wrapper.vm.$nextTick() // 断言逻辑见下一步 })
Vue2 + Vue Test Utils v1 写法
import { createLocalVue, mount } from '@vue/test-utils' import VCalendar from 'v-calendar' import Calendar from './template.vue' // 创建临时Vue实例注册插件,避免污染全局 const localVue = createLocalVue() localVue.use(VCalendar) test('v-calendar 正常渲染', async () => { const wrapper = mount(Calendar, { localVue }) // 后续逻辑和上面一致 })
注意:如果你之前用的是
shallowMount,请替换为mount。shallowMount会默认将所有子组件打为存根,只渲染组件标签壳,和你现在看到的空标签效果完全一致。
2. 用DOM选择器断言替换HTML字符串匹配
不要用wrapper.html()做字符串包含判断,用Vue Test Utils内置的find方法配合CSS选择器判断元素存在,准确率更高,也不会出现把选择器语法写到匹配字符串里的错误:
// 检查日历容器是否存在 expect(wrapper.find('.vc-container').exists()).toBe(true) // 也可以检查你自定义的高亮样式类是否生效 expect(wrapper.find('.date-circle').exists()).toBe(true)
如果遇到时序问题(组件还没渲染完断言就执行了),可以用waitFor工具等待目标元素出现后再断言。
可选优化:单元测试隔离第三方组件
如果你的单元测试只需要校验自身逻辑,不需要覆盖第三方组件的渲染结果,可以直接给v-calendar加存根,不用完整渲染,断言组件传参正确即可,执行速度更快:
test('v-calendar 接收正确的配置参数', async () => { const wrapper = mount(Calendar, { global: { stubs: ['v-calendar'] // 存根v-calendar组件 } }) await wrapper.setData({ locale: { id: 'en' }, attrs: [{ key: 'today', highlight: { class: 'date-circle', contentClass: 'date-text', }, dates: new Date(), }], }) const calendar = wrapper.findComponent({ name: 'VCalendar' }) // 断言props正确传入 expect(calendar.props('isExpanded')).toBe(true) expect(calendar.props('titlePosition')).toBe('left') expect(calendar.props('locale')).toEqual({ id: 'en' }) })
内容的提问来源于stack exchange,提问作者tmein

