Vue+Vitest快照测试中data-v随机属性导致快照不一致问题
Vue组件快照测试中data-v-[随机数]导致快照不一致的问题解决
问题描述
我使用Vite和Vitest对纯模板、无逻辑的Vue组件进行快照测试时,遇到了一个问题:每次生成的快照都不一致,原因是组件的根元素会被自动添加data-v-[随机哈希值]属性。测试报错示例如下:
- Expected ""<span data-v-25e5131c=""></span>"" + Received ""<span data-v-b3462088=""></span>""
示例代码:
BaseText.vue
<script setup lang="ts"></script> <template> <span><slot></slot></span> </template>
BaseText.spec.ts
import { describe, it, expect } from "vitest"; import { shallowMount } from "@vue/test-utils"; import BaseText from "./BaseText.vue"; describe(name, () => { const wrapper = shallowMount(BaseText); it("MatchSnapshot", () => { expect(wrapper.html()).toMatchSnapshot(); }); });
原因分析
data-v-xxx是Vue用于Scoped CSS样式隔离的标识。即使你的组件没有编写<style scoped>代码,Vite的Vue编译插件依然会默认启用Scoped CSS的处理逻辑,为每个组件生成唯一的哈希标识并添加到根元素上。而测试时每次运行生成的哈希值是随机的,这就导致了快照内容无法匹配。
解决方法
方案1:直接取消组件的scopeId(推荐)
在组件的<script setup>中通过defineOptions手动取消scopeId的生成,从根源上避免这个属性出现:
<script setup lang="ts"> defineOptions({ __scopeId: undefined }) </script> <template> <span><slot></slot></span> </template>
方案2:测试时清理HTML中的随机属性
如果不想修改组件代码,可以在测试逻辑中把生成的HTML里的data-v-xxx属性移除后再做快照对比:
import { describe, it, expect } from "vitest"; import { shallowMount } from "@vue/test-utils"; import BaseText from "./BaseText.vue"; describe('BaseText', () => { const wrapper = shallowMount(BaseText); it("MatchSnapshot", () => { // 用正则移除所有data-v-开头的属性 const cleanedHtml = wrapper.html().replace(/data-v-[a-f0-9]+/g, ''); expect(cleanedHtml).toMatchSnapshot(); }); });
方案3:配置Vite固定scopeId生成规则
通过Vite配置文件,让Vue插件生成固定的scopeId,确保每次测试的标识一致:
import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' export default defineConfig({ plugins: [ vue({ template: { compilerOptions: { // 设置固定的scopeId scopeId: 'data-v-fixed' } } }) ] })
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

