如何在Next.js服务端组件中Mock Cookies并解决Vitest测试报错
问题根源
next/headers里的cookies()函数依赖Next.js内部的Request Async Storage上下文,Vitest测试环境默认不会初始化这个上下文,直接调用就会抛出requestAsyncStorage不可用的错误。
具体解决方法
1. 手动Mock存储上下文(通用方案)
在测试文件开头或者全局测试配置里,手动Mock Next.js的存储上下文:
import { vi } from 'vitest'; import { RequestAsyncStorage } from 'next/dist/client/components/request-async-storage'; // 模拟存储实例,自定义cookie返回值 const mockStorage = { getStore: vi.fn(() => ({ cookies: vi.fn(() => ({ get: vi.fn((key) => { // 按需返回特定cookie,比如这里模拟theme=dark if (key === 'theme') return { value: 'dark' }; return null; }), }), })), }; // 替换Next.js的RequestAsyncStorage vi.mock('next/dist/client/components/request-async-storage', () => ({ RequestAsyncStorage: vi.fn(() => mockStorage), }));
2. 用官方测试工具(推荐)
Next.js的next/test-utils提供了setCookies工具,能自动处理上下文,用起来更省心:
import { render, screen } from '@testing-library/react'; import { setCookies } from 'next/test-utils'; import Home from '../app/page'; test('根据cookie渲染深色主题', async () => { // 设置模拟的cookie setCookies([{ name: 'theme', value: 'dark' }]); render(<Home />); // 验证条件渲染结果 expect(screen.getByText('深色主题已启用')).toBeInTheDocument(); });
3. 服务器组件的测试处理
如果测试的是服务器组件,可以直接Mocknext/headers的cookies函数:
import { vi } from 'vitest'; import { cookies } from 'next/headers'; import Home from '../app/page'; // Mock cookies函数的返回值 vi.mock('next/headers', () => ({ cookies: vi.fn(() => ({ get: vi.fn((key) => key === 'theme' ? { value: 'dark' } : null), })), })); test('服务器组件读取cookie并渲染对应内容', async () => { const component = await Home(); expect(component.props.children).toContain('深色主题已启用'); });
额外注意
- 确保你的
vitest.config.ts继承了Next.js配置,比如官方示例里的配置:
import { defineConfig } from 'vitest/config'; import next from '@next/eslint-plugin-next'; export default defineConfig({ plugins: [next()], test: { environment: 'jsdom', }, });
- 用TypeScript的话,可能需要给
next/dist/client/components/request-async-storage加类型声明,避免类型报错。
内容的提问来源于stack exchange,提问作者IObert
相关产品推荐
相关产品推荐

