经过深入调查,API 测试失败的根本原因是:生成的测试代码试图在 Vitest 单元测试环境中运行需要完整 Next.js 运行时环境的 Server Actions。
// tests/api/users-actions.test.ts
const { response, data } = await callActionsRoute({
method: 'POST',
pathname: '/api/actions/users/addUser',
authToken: ADMIN_TOKEN
});
这个测试通过 callActionsRoute 直接调用 Next.js 的 Server Actions 处理器,而不是启动真实服务器后通过 HTTP 请求测试。
Server Actions 代码中广泛使用了 Next.js 特定 API:
cookies() from 'next/headers'
requestAsyncStorage)getTranslations() from 'next-intl/server'
revalidatePath() from 'next/cache'
staticGenerationStore)getLocale() from 'next-intl/server'
尝试:创建 tests/mocks/nextjs.ts Mock 所有 Next.js 特定函数
问题:
getLocale、revalidatePath等)AsyncLocalStorage 上下文结论:治标不治本,维护成本高
测试 /api/actions/* REST API 端点 的正确方式是:
方法:启动真实的 Next.js 开发服务器,通过 HTTP 请求测试
优点:
实现:
// tests/api/integration/users-actions.test.ts
import { beforeAll, afterAll, describe, expect, test } from "vitest";
let serverProcess: ChildProcess;
const API_BASE_URL = "http://localhost:3000";
beforeAll(async () => {
// 启动 Next.js 开发服务器
serverProcess = spawn("npm", ["run", "dev"], {
env: { ...process.env, PORT: "3000" }
});
// 等待服务器准备就绪
await waitForServer(API_BASE_URL);
});
afterAll(() => {
serverProcess.kill();
});
describe("User API Tests", () => {
test("should create user", async () => {
const response = await fetch(`${API_BASE_URL}/api/actions/users/addUser`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Cookie": `auth-token=${process.env.ADMIN_TOKEN}`
},
body: JSON.stringify({
name: "Test User",
rpm: 60,
dailyQuota: 10
})
});
const data = await response.json();
expect(response.ok).toBe(true);
expect(data.ok).toBe(true);
});
});
方法:只测试不依赖 Next.js 运行时的纯业务逻辑
适用范围:
示例:
// tests/unit/repository/users.test.ts
import { describe, expect, test } from "vitest";
import { findUserById, createUser } from "@/repository/user";
describe("User Repository", () => {
test("should find user by ID", async () => {
const user = await findUserById(1);
expect(user).toBeDefined();
expect(user?.id).toBe(1);
});
});
删除或跳过当前失败的 API 测试
// tests/api/users-actions.test.ts
describe.skip("用户管理 - API测试(待重构为集成测试)", () => {
// ... 所有测试
});
原因:
编写集成测试替代
tests/api/integration/ 目录优化代码架构
示例重构:
// Before: 直接调用 Next.js API
export async function addUser(data: CreateUserData) {
const session = await getSession(); // Next.js specific
const t = await getTranslations(); // Next.js specific
// ... business logic
revalidatePath("/dashboard"); // Next.js specific
}
// After: 依赖注入
export async function addUser(
data: CreateUserData,
context: ActionContext // 包含 session, translator, cache
) {
const { session, t, cache } = context;
// ... business logic
cache.revalidate("/dashboard");
}
/api/actions/*)过度依赖 Next.js 特定 API
缺少集成测试基础设施
测试文档缺失
describe.skip)tests/mocks/nextjs.ts)结论:当前的测试失败不是 Bug,而是测试设计与技术架构不匹配导致的。建议采用集成测试方案重写 API 测试。
状态:已诊断 ✅ 下一步:跳过当前测试 + 规划集成测试框架