实战

Claude Code Vitest 单元测试实战:AI 辅助前端测试完全指南(2026)

Claude Code 辅助 Vitest 单元测试完整实战:安装配置(globals/jsdom/coverage)、工具函数测试生成(正常/边界/异常三类)、Vue 组件测试(Props/emit/loading/error状态)、Pinia Store 测试(beforeEach重置/计算属性验证)、覆盖率报告生成,附批量生成/Jest迁移/async mock Prompt 模板。

2026/3/305分钟 阅读ClaudeEagle

Vitest 是 Vite 生态的现代单元测试框架—— 与 Jest API 兼容,速度快 10 倍以上。 Claude Code 能快速生成覆盖率高、可维护的 Vitest 测试。

为什么选 Vitest?

Vitest vs Jest: 速度:Vitest 利用 Vite 的 ESM 原生支持,快 5-10 倍 配置:零配置,和 Vite 项目天然集成 API:与 Jest 完全兼容,迁移成本极低 TypeScript:原生支持,无需 ts-jest HMR:文件变更时只重跑受影响的测试

安装配置

bash
npm install -D vitest @vitest/ui @testing-library/vue
# 或 React 项目:
npm install -D vitest @vitest/ui @testing-library/react jsdom
typescript
// vite.config.ts
import { defineConfig } from 'vite'
import { defineConfig as defineVitest } from 'vitest/config'

export default defineConfig({
  test: {
    globals: true,           // 不需要 import { describe, it, expect }
    environment: 'jsdom',    // 模拟浏览器环境
    setupFiles: ['./tests/setup.ts'],
    coverage: {
      provider: 'v8',
      reporter: ['text', 'html'],
      thresholds: { lines: 80, functions: 80 }
    }
  }
})

场景一:让 Claude Code 生成工具函数测试

Prompt:

帮我为 src/utils/format.ts 里的所有工具函数 写完整的 Vitest 单元测试: - 正常输入的预期输出 - 边界条件(空值/null/undefined/极端值) - 异常情况(应该抛出错误的场景) 覆盖率目标 > 90%

假设 format.ts 包含:

typescript
// src/utils/format.ts
export function formatCurrency(amount: number, currency = 'CNY'): string {
  if (amount < 0) throw new Error('Amount cannot be negative')
  return new Intl.NumberFormat('zh-CN', {
    style: 'currency', currency
  }).format(amount)
}

export function truncate(str: string, maxLen: number): string {
  if (!str) return ''
  return str.length <= maxLen ? str : str.slice(0, maxLen) + '...'
}

Claude Code 生成的测试:

typescript
// tests/utils/format.test.ts
import { describe, it, expect } from 'vitest'
import { formatCurrency, truncate } from '../../src/utils/format'

describe('formatCurrency', () => {
  it('正确格式化整数金额', () => {
    expect(formatCurrency(1000)).toBe('¥1,000.00')
  })

  it('正确格式化小数金额', () => {
    expect(formatCurrency(99.9)).toBe('¥99.90')
  })

  it('支持其他货币', () => {
    expect(formatCurrency(100, 'USD')).toContain('$')
  })

  it('金额为零时返回零', () => {
    expect(formatCurrency(0)).toBe('¥0.00')
  })

  it('负数金额抛出错误', () => {
    expect(() => formatCurrency(-1)).toThrow('Amount cannot be negative')
  })
})

describe('truncate', () => {
  it('短字符串不截断', () => {
    expect(truncate('hello', 10)).toBe('hello')
  })

  it('超长字符串截断并加省略号', () => {
    expect(truncate('hello world', 5)).toBe('hello...')
  })

  it('恰好等于最大长度不截断', () => {
    expect(truncate('hello', 5)).toBe('hello')
  })

  it('空字符串返回空字符串', () => {
    expect(truncate('', 10)).toBe('')
  })

  it('null/undefined 返回空字符串', () => {
    expect(truncate(null as any, 10)).toBe('')
    expect(truncate(undefined as any, 10)).toBe('')
  })
})

场景二:Vue 组件测试

Prompt:

帮我给这个 UserCard.vue 组件写 Vitest 测试: - 测试 Props 渲染(name/avatar/role) - 测试 click 事件 emit - 测试 loading 状态下显示骨架屏 - 测试 error 状态下显示错误提示
typescript
// tests/components/UserCard.test.ts
import { describe, it, expect, vi } from 'vitest'
import { mount } from '@vue/test-utils'
import UserCard from '../../src/components/UserCard.vue'

describe('UserCard', () => {
  const defaultProps = {
    name: '张三',
    avatar: 'https://example.com/avatar.jpg',
    role: '管理员'
  }

  it('正确渲染用户信息', () => {
    const wrapper = mount(UserCard, { props: defaultProps })
    expect(wrapper.text()).toContain('张三')
    expect(wrapper.text()).toContain('管理员')
    expect(wrapper.find('img').attributes('src')).toBe(defaultProps.avatar)
  })

  it('点击卡片触发 select emit', async () => {
    const wrapper = mount(UserCard, { props: defaultProps })
    await wrapper.trigger('click')
    expect(wrapper.emitted('select')).toHaveLength(1)
    expect(wrapper.emitted('select')?.[0]).toEqual([defaultProps])
  })

  it('loading 状态显示骨架屏', () => {
    const wrapper = mount(UserCard, {
      props: { ...defaultProps, loading: true }
    })
    expect(wrapper.find('[data-testid="skeleton"]').exists()).toBe(true)
    expect(wrapper.find('[data-testid="user-name"]').exists()).toBe(false)
  })
})

场景三:Pinia Store 测试

Prompt:

帮我给购物车 Pinia Store 写完整测试, 包括 addItem / removeItem / totalPrice 计算属性
typescript
import { describe, it, expect, beforeEach } from 'vitest'
import { setActivePinia, createPinia } from 'pinia'
import { useCartStore } from '../../src/stores/cart'

describe('useCartStore', () => {
  beforeEach(() => {
    setActivePinia(createPinia())  // 每次测试重置 Store
  })

  it('初始状态购物车为空', () => {
    const cart = useCartStore()
    expect(cart.items).toHaveLength(0)
    expect(cart.totalPrice).toBe(0)
  })

  it('添加商品', () => {
    const cart = useCartStore()
    cart.addItem({ id: 1, name: 'iPhone', price: 5999 })
    expect(cart.items).toHaveLength(1)
    expect(cart.items[0].quantity).toBe(1)
  })

  it('重复添加同一商品增加数量', () => {
    const cart = useCartStore()
    cart.addItem({ id: 1, name: 'iPhone', price: 5999 })
    cart.addItem({ id: 1, name: 'iPhone', price: 5999 })
    expect(cart.items).toHaveLength(1)
    expect(cart.items[0].quantity).toBe(2)
  })

  it('正确计算总价', () => {
    const cart = useCartStore()
    cart.addItem({ id: 1, name: 'A', price: 100 })
    cart.addItem({ id: 1, name: 'A', price: 100 })  // quantity = 2
    cart.addItem({ id: 2, name: 'B', price: 200 })
    expect(cart.totalPrice).toBe(400)
  })
})

覆盖率报告

bash
# 运行测试并生成覆盖率报告
npx vitest run --coverage

# 打开可视化报告
npx vitest --ui

# CI 中强制覆盖率门槛
npx vitest run --coverage --coverage.thresholds.lines=80

高效 Prompt 模板

[批量生成测试] 分析 src/utils/ 目录下所有工具函数, 为每个函数生成完整的 Vitest 测试, 覆盖正常/边界/异常三类情况,目标覆盖率 90%。 [迁移 Jest 测试] 把这个 Jest 测试文件迁移到 Vitest, 保持测试逻辑不变,使用 Vitest 的最佳实践: [粘贴 Jest 测试文件] [测试 async 函数] 这个异步函数会调用外部 API, 帮我用 Vitest 的 vi.mock 模拟 API, 写完整的测试(成功/失败/超时三种情况): [粘贴函数代码]

来源:Vitest 官方文档 vitest.dev + Anthropic Claude Code 文档

相关文章推荐

实战Claude Code Vue 3 实战完全指南:Composition API 开发到企业级前端工程化Claude Code 辅助 Vue 3 开发的完整实战指南:Composition API 组件生成(setup/ref/computed)、Pinia 状态管理代码生成、Vue Router 4 路由配置、TypeScript 类型定义生成(Props/Emits)、Composables 抽象、Vitest 单元测试生成、性能优化(虚拟滚动/v-memo),以及 Options API 迁移和响应式丢失问题排查的 Prompt 模板。2026/3/26实战Claude Code 测试覆盖率提升实战:从 30% 到 80% 的系统化方法用 Claude Code 系统性提升测试覆盖率的完整方法:快速识别覆盖率盲区(Istanbul/Coverage.py 报告解读)、让 Claude 针对未覆盖行生成测试的精准提示词、边界条件和异常路径的自动发现、集成测试 vs 单元测试的覆盖率策略、Mock 复杂依赖(数据库/HTTP/时间)的方法、测试质量 vs 测试数量的平衡、以及在 CI 中设置覆盖率门禁阻止质量退化。2026/3/21实战Claude Code 测试驱动开发(TDD)实战:AI 辅助红绿重构循环完全指南Claude Code 与测试驱动开发(TDD)深度结合实战:让 Claude 先写测试再写实现的完整工作流、Red-Green-Refactor 循环的 AI 辅助方式、测试用例描述转换为 Jest/pytest/Go test 测试代码、边界条件和异常路径的自动发现、用 Claude 做变异测试(Mutation Testing)发现测试盲区、提升测试质量的提示词技巧,以及 TDD 在遗留代码改造中的应用方法。2026/3/20实战Claude Code 自动生成测试用例:单元测试、集成测试和 E2E 测试完整指南Claude Code 自动生成测试用例完整指南:从函数签名生成边界条件测试、Table-Driven 测试模式、Mock 依赖注入、集成测试数据库 Fixtures、Playwright E2E 测试生成,以及提升测试覆盖率的系统化 Prompt 策略和 TDD 工作流。2026/3/16实战用 AI 写单元测试:Claude Code 自动化测试生成完全指南Claude Code AI 自动化测试生成完全指南:为什么 AI 特别适合写测试、Jest/pytest/JUnit 三大框架使用示例、四大高价值测试场景(提升覆盖率/TDD/回归测试/批量补测试)、高质量测试 Prompt 写法、CLAUDE.md 固化测试规范与常见问题解答。2026/3/14实战Claude Code React Server Components 实战:Next.js 15 RSC 开发完全指南(2026)Claude Code 辅助 React Server Components(RSC)开发完整指南:服务端 vs 客户端组件选择原则、服务端直连数据库的页面写法、客户端交互组件 + Server Action 乐观更新、Suspense 流式渲染(主内容快速显示+慢数据不阻塞)、三类常见 RSC 错误诊断(useState/Event Handlers/Hydration),适配 Next.js 15。2026/3/30