如何在Next.js+Jest中测试cookies.set方法的调用次数
问题原因
你当前的mock设置中,每次调用cookies()都会生成一个全新的包含set方法的对象。这意味着:
handleLoginAction里两次调用cookies()时,各自拿到的是不同的setmock函数- 你测试代码里调用
cookies().set拿到的又是另一个全新的setmock函数
自然断言调用次数为0,因为这个mock函数根本没被执行过。
解决方案
修改mock逻辑,让cookies()每次调用都返回同一个对象,这样所有地方用到的set都是同一个mock函数。
修改后的测试代码示例
import { AuthService } from '@services'; import { FormStateType } from '@types'; import { cookies } from 'next/headers'; import { redirect } from 'next/navigation'; import { handleLoginAction } from './useLogin.hook'; // 提前创建共享的mock cookie store对象 const mockCookieStore = { set: jest.fn(), }; jest.mock('next/navigation', () => ({ ...jest.requireActual('next/navigation'), redirect: jest.fn(), })); jest.mock('next/headers', () => ({ ...jest.requireActual('next/headers'), // 让cookies()始终返回同一个mock对象 cookies: jest.fn(() => mockCookieStore), })); describe('UseLogin hook tests', () => { describe('handleLoginAction tests', () => { it('Returns form state on success request', async () => { const formState: FormStateType = {}; const formData: FormData = new FormData(); const loginResponse: any = { access_token: 'access_token', refresh_token: 'refresh_token' }; jest.spyOn(AuthService.prototype, 'login').mockResolvedValueOnce(loginResponse); const result: FormStateType = await handleLoginAction(formState, formData); expect(result).toBeUndefined(); expect(redirect).toHaveBeenCalled(); // 直接断言共享的mockSet函数的调用次数 expect(mockCookieStore.set).toHaveBeenCalledTimes(2); // 还可以进一步验证调用参数是否正确 expect(mockCookieStore.set).toHaveBeenCalledWith(COOKIES_KEYS.ACCESS, 'access_token'); expect(mockCookieStore.set).toHaveBeenCalledWith(COOKIES_KEYS.REFRESH, 'refresh_token'); }); }); });
另一种实现方式
如果不想提前创建共享对象,也可以在测试用例中先获取mock的cookies实例,但前提是mock的cookies()返回同一个对象:
// mock部分返回同一个set函数实例 jest.mock('next/headers', () => { const mockSet = jest.fn(); return { ...jest.requireActual('next/headers'), cookies: jest.fn(() => ({ set: mockSet })), }; }); // 在测试用例中获取并断言 it('Returns form state on success request', async () => { const formState: FormStateType = {}; const formData: FormData = new FormData(); const loginResponse: any = { access_token: 'access_token', refresh_token: 'refresh_token' }; jest.spyOn(AuthService.prototype, 'login').mockResolvedValueOnce(loginResponse); await handleLoginAction(formState, formData); expect(redirect).toHaveBeenCalled(); // 获取mock的set函数并断言 const mockSet = (cookies() as ReturnType<typeof cookies>).set; expect(mockSet).toHaveBeenCalledTimes(2); });
内容的提问来源于stack exchange,提问作者William Rizzi
相关产品推荐
相关产品推荐

