You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue3+Pinia项目:如何为含第三方异步API的Store编写测试用例?

适配Vue3+Vuetify3+Vite+Pinia+TypeScript的Jest测试配置及Pinia异步Action测试方案

一、Jest测试环境配置

1. 安装依赖

首先安装所需测试工具包:

npm install -D jest @types/jest ts-jest @vue/vue3-jest @vue/test-utils pinia @pinia/testing jsdom

2. 配置jest.config.ts

在项目根目录创建jest.config.ts,适配技术栈规则:

import type { Config } from 'jest'
import { createVueJestPreset } from '@vue/vue3-jest'

const config: Config = {
  ...createVueJestPreset({ compiler: 'vue3' }),
  preset: 'ts-jest',
  testEnvironment: 'jsdom',
  moduleFileExtensions: ['ts', 'js', 'vue'],
  transform: {
    '^.+\\.ts$': 'ts-jest',
    '^.+\\.vue$': '@vue/vue3-jest'
  },
  moduleNameMapper: {
    '^@/(.*)$': '<rootDir>/src/$1' // 匹配Vite中@的路径别名
  },
  setupFilesAfterEnv: ['<rootDir>/tests/setup.ts'],
  testMatch: ['<rootDir>/tests/**/*.spec.ts'],
  globals: {
    'ts-jest': {
      tsconfig: '<rootDir>/tsconfig.json'
    }
  }
}

export default config

3. 全局测试初始化(setup.ts)

在tests目录下创建setup.ts,处理全局依赖注入:

import { config } from '@vue/test-utils'
import { createTestingPinia } from '@pinia/testing'
import { createVuetify } from 'vuetify'
import * as components from 'vuetify/components'
import * as directives from 'vuetify/directives'

// 初始化Vuetify
const vuetify = createVuetify({
  components,
  directives
})

// 全局注册测试所需插件
config.global.plugins.push(
  createTestingPinia({ createSpy: jest.fn }),
  vuetify
)

二、含第三方异步API的Pinia Store Action测试方法

核心思路是Mock第三方API隔离外部依赖,专注测试Store的业务逻辑(状态更新、错误处理、API调用校验等)。

1. 基础Mock示例(全量Mock API服务)

假设Store Action包含第三方API调用,测试时直接Mock整个API模块:

// tests/stores/[your-store].spec.ts
import { useYourStore } from '@/stores/your-store'
import apiService from '@/services/api'

// Mock整个API服务
jest.mock('@/services/api', () => ({
  fetchTargetData: jest.fn() // 替换为你的实际API方法名
}))

describe('useYourStore - async action', () => {
  // 测试成功场景
  it('fetches data and updates state correctly', async () => {
    // 预设Mock返回值
    const mockResponse = { data: { id: '1', content: 'test content' } }
    (apiService.fetchTargetData as jest.Mock).mockResolvedValue(mockResponse)

    const store = useYourStore()
    await store.yourAsyncAction('1') // 调用你的异步Action

    // 校验API调用参数
    expect(apiService.fetchTargetData).toHaveBeenCalledWith('1')
    // 校验状态更新
    expect(store.loading).toBe(false)
    expect(store.targetData).toEqual(mockResponse.data)
    expect(store.error).toBeNull()
  })

  // 测试失败场景
  it('handles API error properly', async () => {
    const mockError = new Error('Failed to connect API')
    (apiService.fetchTargetData as jest.Mock).mockRejectedValue(mockError)

    const store = useYourStore()
    await store.yourAsyncAction('1')

    expect(apiService.fetchTargetData).toHaveBeenCalledWith('1')
    expect(store.loading).toBe(false)
    expect(store.targetData).toBeNull()
    expect(store.error).toBe('Failed to connect API')
  })
})

2. 进阶:局部Mock单个API方法

如果不需要Mock整个API服务,可单独Mock目标方法:

import { useYourStore } from '@/stores/your-store'
import * as apiService from '@/services/api'

describe('useYourStore', () => {
  it('fetches data successfully', async () => {
    // Mock单个API方法
    const mockFetch = jest.spyOn(apiService, 'fetchTargetData').mockResolvedValue({ data: {} })

    const store = useYourStore()
    await store.yourAsyncAction('1')

    expect(mockFetch).toHaveBeenCalledWith('1')
    // 测试后恢复原方法,避免影响其他测试用例
    mockFetch.mockRestore()
  })
})

3. 关键注意点

  • 使用createTestingPinia时,默认不开启stubActions: true,确保真实Action逻辑被执行;若需Mock Action本身,再开启该配置。
  • TypeScript类型断言:Mock后若出现类型报错,用as jest.Mock明确类型即可。
  • Vuetify相关依赖已通过setup.ts全局注入,无需在单测中重复配置。

内容的提问来源于stack exchange,提问作者Nallamachu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 10:24:59