关于 unit-test-vue-pinia
用于创建和审查 Vue 组件、composable 与 Pinia store 单元测试的技能。它强调小型、确定性且关注可观察行为的测试,并指导选择精简的 Pinia 配置。
主要功能
- 01以行为为先设计测试
- 02Pinia 配置与 action 存根指导
- 03Vue Test Utils 交互模式
- 04断言可观察输出与副作用
- 05检查覆盖缺口和脆弱测试
适用场景
- 01为 Vue 组件编写聚焦测试
- 02测试 composable 或 Pinia store 行为
- 03审查脆弱或依赖内部实现的断言
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ github/ awesome-copilot --skill unit-test-vue-pinia安装后在 Claude Code 中输入/unit-test-vue-pinia确认已加载。
附带文件references/pinia-patterns.md
详细介绍
unit-test-vue-pinia
使用本技能为 Vue 组件、组合式函数和 Pinia store 创建或审查单元测试。保持测试小而精、确定性、行为优先。
工作流
- 先确定行为边界:组件 UI 行为、组合式函数行为或 store 行为。
- 选择能证明该行为的最窄测试方式。
- 用仍能覆盖场景的最弱选项来设置 Pinia。
- 通过公开输入驱动测试,例如 props、表单更新、按钮点击、子组件发出的事件以及 store API。
- 优先断言可观察的输出和副作用,再考虑任何实例级断言。
- 返回或审查测试时使用清晰的行为导向命名,并注明任何剩余的覆盖率缺口。
核心规则
- 每个测试只测一个行为。
- 优先断言可观察的输入/输出行为(渲染文本、发出的事件、回调调用、store 状态变化)。
- 避免与实现耦合的断言。
- 只有在没有合理的 DOM、prop、emit 或 store 层级断言时,才在例外情况下访问
wrapper.vm。 - 优先在
beforeEach()中进行显式设置,并在每个测试中重置 mock。 - 使用
references/pinia-patterns.md中签入的参考资料作为标准 Pinia 测试设置的本地事实来源。
Pinia 测试方法
先使用 references/pinia-patterns.md,当签入示例未覆盖该场景时,再回退到 Pinia 的测试 cookbook。
组件测试的默认模式
在挂载时使用 createTestingPinia 作为全局插件。
优先将 createSpy: vi.fn 作为默认项,以保持一致性并更轻松地进行 action spy 断言。
const wrapper = mount(ComponentUnderTest, {
global: {
plugins: [
createTestingPinia({
createSpy: vi.fn,
}),
],
},
});
默认情况下,action 会被打桩并设置 spy。
当测试只需验证某个 action 是否被调用(或未被调用)时,使用 stubActions: true(默认值)。
可接受的最小 Pinia 设置
以下做法同样有效,不应被标记为错误:
- 当测试不断言 Pinia action spy 行为时,使用
createTestingPinia({})。 - 当测试只需状态播种或 action 打桩行为而不检查生成的 spy 时,使用不带
createSpy的createTestingPinia({ initialState: ... })或createTestingPinia({ stubActions: ... })。 - 在以 store/组合式函数为重点的测试中(不挂载组件),当需要 mock/播种依赖 store 时,使用
setActivePinia(createTestingPinia(...))。
当 action spy 断言属于测试意图时,使用 createSpy: vi.fn。
仅在需要时执行真实 action
仅当测试必须验证 action 的真实行为和副作用时,才使用 stubActions: false。不要为简单的「是否被调用」断言默认开启它。
const wrapper = mount(ComponentUnderTest, {
global: {
plugins: [
createTestingPinia({
createSpy: vi.fn,
stubActions: false,
}),
],
},
});
用 initialState 播种 store 状态
const wrapper = mount(ComponentUnderTest, {
global: {
plugins: [
createTestingPinia({
createSpy: vi.fn,
initialState: {
counter: { n: 20 },
user: { name: "Leia Organa" },
},
}),
],
},
});
通过 createTestingPinia 添加 Pinia 插件
const wrapper = mount(ComponentUnderTest, {
global: {
plugins: [
createTestingPinia({
createSpy: vi.fn,
plugins: [myPiniaPlugin],
}),
],
},
});
针对边缘情况的 getter 覆盖模式
const pinia = createTestingPinia({ createSpy: vi.fn });
const store = useCounterStore(pinia);
store.double = 999;
// @ts-expect-error test-only reset of overridden getter
store.double = undefined;
纯 store 单元测试
当目标是在不渲染组件的情况下验证 store 状态转换和 action 行为时,优先使用 createPinia() 进行纯 store 测试。仅当你需要打桩的依赖 store、播种的测试替身或 action spy 时,才使用 createTestingPinia()。
beforeEach(() => {
setActivePinia(createPinia());
});
it("increments", () => {
const counter = useCounterStore();
counter.increment();
expect(counter.n).toBe(1);
});
Vue Test Utils 方法
遵循 Vue Test Utils 指南:https://test-utils.vuejs.org/guide/
- 对于专注的单元测试,默认进行浅挂载。
- 仅当集成行为是测试对象时,才挂载完整组件树。
- 通过 props、类用户交互和发出的事件来驱动行为。
- 对于子组件 stub 事件,优先使用
findComponent(...).vm.$emit(...),而不是触碰父组件内部。 - 仅在更新为异步时使用
nextTick。 - 使用
wrapper.emitted(...)断言发出的事件和载荷。 - 仅当没有 DOM 断言、发出事件断言、prop 断言或 store 层级断言能表达该行为时,才访问
wrapper.vm。将其视为例外,并保持断言范围狭窄。
关键测试片段
发出并断言载荷:
await wrapper.find("button").trigger("click");
expect(wrapper.emitted("submit")?.[0]?.[0]).toBe("Mango Mission");
更新输入并断言输出:
await wrapper.find("input").setValue("Agent Violet");
await wrapper.find("form").trigger("submit");
expect(wrapper.emitted("save")?.[0]?.[0]).toBe("Agent Violet");
测试编写工作流
- 确定要测试的行为边界。
- 构建最小化的 fixture 数据(仅包含该行为所需的字段)。
- 配置 Pinia 及所需的测试替身。
- 通过公共输入触发行为。
- 断言公共输出与副作用。
- 重构测试名称,使其描述行为而非实现。
约束与安全
- 不要测试私有/内部实现细节。
- 不要对动态 UI 行为过度使用快照。
- 如果只有一个行为重要,不要断言大型对象中的每个字段。
- 保持伪造数据具有确定性;避免随机值。
- 当 Pinia 配置属于上述已接受的最小配置之一时,不要声称它是错误的。
- 除非被测行为需要额外的接触面,否则不要将可正常工作的测试改写为更深层挂载或真实 action。
- 在评审期间明确标记缺失的测试覆盖、脆弱的 selector 以及与实现耦合的断言。
输出约定
- 对于
create或update,返回完成的测试代码,并附上一条简短说明,描述所选的 Pinia 策略。 - 对于
review,先返回具体发现,然后返回缺失的覆盖或脆弱性风险。 - 当最安全的选择存在歧义时,说明促使你选择该测试设置的假设。
参考
references/pinia-patterns.md- Pinia 测试 cookbook:https://pinia.vuejs.org/cookbook/testing.html
- Vue Test Utils 指南:https://test-utils.vuejs.org/guide/