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
相关产品推荐
相关产品推荐

