mcpField
U
unit-test-vue-pinia

unit-test-vue-pinia

github.com/github测试与质量40.5k1.8k 次安装今天更新
代码仓库

关于 unit-test-vue-pinia

用于创建和审查 Vue 组件、composable 与 Pinia store 单元测试的技能。它强调小型、确定性且关注可观察行为的测试,并指导选择精简的 Pinia 配置。

主要功能

  1. 01以行为为先设计测试
  2. 02Pinia 配置与 action 存根指导
  3. 03Vue Test Utils 交互模式
  4. 04断言可观察输出与副作用
  5. 05检查覆盖缺口和脆弱测试

适用场景

  1. 01为 Vue 组件编写聚焦测试
  2. 02测试 composable 或 Pinia store 行为
  3. 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 创建或审查单元测试。保持测试小而精、确定性、行为优先。

工作流

  1. 先确定行为边界:组件 UI 行为、组合式函数行为或 store 行为。
  2. 选择能证明该行为的最窄测试方式。
  3. 用仍能覆盖场景的最弱选项来设置 Pinia。
  4. 通过公开输入驱动测试,例如 props、表单更新、按钮点击、子组件发出的事件以及 store API。
  5. 优先断言可观察的输出和副作用,再考虑任何实例级断言。
  6. 返回或审查测试时使用清晰的行为导向命名,并注明任何剩余的覆盖率缺口。

核心规则

  • 每个测试只测一个行为。
  • 优先断言可观察的输入/输出行为(渲染文本、发出的事件、回调调用、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");

测试编写工作流

  1. 确定要测试的行为边界。
  2. 构建最小化的 fixture 数据(仅包含该行为所需的字段)。
  3. 配置 Pinia 及所需的测试替身。
  4. 通过公共输入触发行为。
  5. 断言公共输出与副作用。
  6. 重构测试名称,使其描述行为而非实现。

约束与安全

  • 不要测试私有/内部实现细节。
  • 不要对动态 UI 行为过度使用快照。
  • 如果只有一个行为重要,不要断言大型对象中的每个字段。
  • 保持伪造数据具有确定性;避免随机值。
  • 当 Pinia 配置属于上述已接受的最小配置之一时,不要声称它是错误的。
  • 除非被测行为需要额外的接触面,否则不要将可正常工作的测试改写为更深层挂载或真实 action。
  • 在评审期间明确标记缺失的测试覆盖、脆弱的 selector 以及与实现耦合的断言。

输出约定

  • 对于 create 或 update,返回完成的测试代码,并附上一条简短说明,描述所选的 Pinia 策略。
  • 对于 review,先返回具体发现,然后返回缺失的覆盖或脆弱性风险。
  • 当最安全的选择存在歧义时,说明促使你选择该测试设置的假设。

参考

评论

支持 Markdown