如何在Vitest中对登录成功后的Cookie创建进行单元测试?
修复Vitest单元测试的问题
原测试代码的核心问题
- 重复mock模块:多次调用
vi.mock("./auth.js")会覆盖之前的mock,导致只有最后一个mock生效,useCookie、useAPIFetch等mock无法正确工作。 - 未初始化Pinia:测试Pinia store必须先创建Pinia实例并安装,否则store无法正常初始化。
- 错误调用Store:直接使用导出的
useAuthStore而不是通过Pinia实例获取的store对象,导致状态重置和方法调用异常。 - Mock不完整:
useCookie的mock没有正确模拟可赋值的value属性,且未处理state初始化和login方法中两次调用useCookie的场景。
修正后的测试代码
import { describe, test, expect, vi, beforeEach } from "vitest"; import { createPinia, setActivePinia } from "pinia"; import { useAuthStore } from "./auth"; // 正确mock Nuxt全局工具函数(这些不是auth.js导出的,是Nuxt提供的) vi.mock("#app", () => ({ useCookie: vi.fn(), useAPIFetch: vi.fn(), navigateTo: vi.fn(), })); import { useCookie, useAPIFetch, navigateTo } from "#app"; describe("useAuthStore", () => { let store; beforeEach(() => { // 初始化Pinia const pinia = createPinia(); setActivePinia(pinia); // 创建store实例 store = useAuthStore(); // 清空所有mock调用记录 useCookie.mockClear(); useAPIFetch.mockClear(); navigateTo.mockClear(); // 模拟state初始化时的useCookie调用 useCookie.mockReturnValue({ value: null }); }); test("login action should update session state and set cookie", async () => { const responseData = { token: "fakeToken" }; // 模拟login里的useCookie调用,返回带有可写value的对象 const mockCookie = { value: null }; useCookie.mockReturnValueOnce(mockCookie); // 模拟API请求成功 useAPIFetch.mockResolvedValue({ data: { value: responseData }, }); await store.login({ username: "user", password: "pass" }); // 验证session状态更新 expect(store.session).toEqual(responseData); // 验证cookie的value被赋值 expect(mockCookie.value).toEqual(responseData); // 验证useCookie的调用参数 expect(useCookie).toHaveBeenNthCalledWith(1, "session"); // state初始化时的调用 expect(useCookie).toHaveBeenNthCalledWith(2, "session", { maxAge: 86400, sameSite: true, }); // login里的调用 // 验证API请求参数 expect(useAPIFetch).toHaveBeenCalledWith("/login", { method: "POST", body: { username: "user", password: "pass" }, }); }); test("logout action should reset session state and navigate to login", () => { // 设置初始session状态 store.session = { token: "fakeToken" }; // 模拟logout里的useCookie调用 const mockCookie = { value: { token: "fakeToken" } }; useCookie.mockReturnValue(mockCookie); store.logout(); // 验证session状态重置 expect(store.session).toBeNull(); // 验证cookie的value被置空 expect(mockCookie.value).toBeNull(); // 验证导航调用 expect(navigateTo).toHaveBeenCalledWith("/login"); }); });
关键修正说明
- 正确Mock全局依赖:
useCookie、useAPIFetch、navigateTo是Nuxt的全局工具,需要mock#app模块而不是./auth.js。 - Pinia初始化:每次测试前创建新的Pinia实例并设置为活跃状态,保证测试隔离。
- Store实例管理:通过
useAuthStore()获取store实例,而不是直接使用导出的函数,确保状态正确绑定。 - Mock多场景调用:区分state初始化和login/logout中
useCookie的不同调用,模拟可写的value属性以验证赋值逻辑。 - 精准验证调用顺序:使用
toHaveBeenNthCalledWith验证useCookie的两次调用参数,确保逻辑符合预期。
内容的提问来源于stack exchange,提问作者booleanbydesign
相关产品推荐
相关产品推荐

