Vitest测试 vitest-testing

Vitest是一个基于Vite的快速JavaScript/TypeScript测试框架,专为现代前端和后端开发设计。它支持单元测试、集成测试、代码覆盖率检查、模拟和热模块替换等功能,适用于测试自动化、性能优化和代码质量保证。关键词:测试、JavaScript、TypeScript、Vite、单元测试、集成测试、模拟、代码覆盖率、测试框架。

测试 0 次安装 0 次浏览 更新于 3/7/2026

名称: vitest-testing 描述: 使用Vitest进行现代TypeScript/JavaScript测试。快速的单元和集成测试,原生ESM支持,Vite驱动的热模块替换,以及全面的模拟。用于测试TS/JS项目。 允许的工具: Bash, Read, Edit, Write, Grep, Glob, TodoWrite

Vitest 测试

使用Vitest测试JavaScript/TypeScript项目的专家知识——一个基于Vite构建的极快测试框架。

快速入门

安装

# 使用Bun(推荐)
bun add -d vitest

# 使用npm
npm install -D vitest

配置

// vitest.config.ts
import { defineConfig } from 'vitest/config'

export default defineConfig({
  test: {
    globals: true,
    environment: 'node', // 或 'jsdom'
    coverage: {
      provider: 'v8',
      reporter: ['text', 'json', 'html'],
      thresholds: { lines: 80, functions: 80, branches: 80 },
    },
    include: ['**/*.{test,spec}.{js,ts,jsx,tsx}'],
  },
})

运行测试

# 运行所有测试(推荐使用bun)
bun test

# 监视模式(默认)
bun test --watch

# 运行一次(CI模式)
bun test --run

# 带覆盖率
bun test --coverage

# 特定文件
bun test src/utils/math.test.ts

# 模式匹配
bun test --grep="calculates sum"

# UI模式(交互式)
bun test --ui

# 详细输出
bun test --reporter=verbose

编写测试

基本结构

import { describe, it, expect, beforeEach, afterEach } from 'vitest'
import { add, subtract } from './math'

describe('数学工具', () => {
  beforeEach(() => {
    // 每个测试前的设置
  })

  it('正确添加两个数字', () => {
    expect(add(2, 3)).toBe(5)
  })

  it('正确减去两个数字', () => {
    expect(subtract(5, 3)).toBe(2)
  })
})

参数化测试

describe.each([
  { input: 2, expected: 4 },
  { input: 3, expected: 9 },
])('平方函数', ({ input, expected }) => {
  it(`将${input}平方为${expected}`, () => {
    expect(square(input)).toBe(expected)
  })
})

断言

// 相等性
expect(value).toBe(expected)
expect(value).toEqual(expected)

// 真实性
expect(value).toBeTruthy()
expect(value).toBeNull()
expect(value).toBeDefined()

// 数字
expect(number).toBeGreaterThan(3)
expect(number).toBeCloseTo(0.3, 1)

// 字符串/数组
expect(string).toMatch(/pattern/)
expect(array).toContain(item)

// 对象
expect(object).toHaveProperty('key')
expect(object).toMatchObject({ a: 1 })

// 异常
expect(() => throwError()).toThrow('message')

// 承诺
await expect(promise).resolves.toBe(value)
await expect(promise).rejects.toThrow()

模拟

函数模拟

import { vi } from 'vitest'

const mockFn = vi.fn()
mockFn.mockReturnValue(42)
mockFn.mockResolvedValue('async result')
mockFn.mockImplementation((x) => x * 2)

expect(mockFn).toHaveBeenCalled()
expect(mockFn).toHaveBeenCalledWith('arg')

模块模拟

vi.mock('./api', () => ({
  fetchUser: vi.fn(() => ({ id: 1, name: '测试用户' })),
}))

import { fetchUser } from './api'

beforeEach(() => {
  vi.clearAllMocks()
})

定时器

beforeEach(() => vi.useFakeTimers())
afterEach(() => vi.restoreAllMocks())

it('推进定时器', () => {
  const callback = vi.fn()
  setTimeout(callback, 1000)
  vi.advanceTimersByTime(1000)
  expect(callback).toHaveBeenCalledOnce()
})

it('模拟日期', () => {
  const date = new Date('2024-01-01')
  vi.setSystemTime(date)
  expect(Date.now()).toBe(date.getTime())
})

覆盖率

# 生成覆盖率报告
bun test --coverage

# HTML报告
bun test --coverage --coverage.reporter=html
open coverage/index.html

# 检查阈值
bun test --coverage --coverage.thresholds.lines=90

集成测试

import request from 'supertest'
import { app } from './app'

describe('API端点', () => {
  it('创建用户', async () => {
    const response = await request(app)
      .post('/api/users')
      .send({ name: 'John' })
      .expect(201)

    expect(response.body).toMatchObject({
      id: expect.any(Number),
      name: 'John',
    })
  })
})

最佳实践

  • 每个源文件对应一个测试文件:math.tsmath.test.ts
  • 使用describe()块分组相关测试
  • 使用描述性测试名称
  • 仅模拟外部依赖项
  • 对独立的异步测试使用concurrent
  • 使用beforeAll()共享昂贵的夹具
  • 目标覆盖率达到80%以上,但不要追求100%

另请参阅

  • test-quality-analysis - 检测测试异味
  • playwright-testing - E2E测试
  • mutation-testing - 验证测试有效性