如何用Jest模拟supabase.auth.signUp并支持多测试场景动态返回值?
解决Jest模拟Supabase auth.signUp时解构data出现undefined的问题
在自定义封装Supabase的signUp方法时,使用Jest的jest.fn()模拟supabase.auth.signUp后,封装函数中解构await返回值的data属性时出现undefined,同时普通JS函数模拟无法满足不同测试用例返回不同结果的需求。以下是解决方案:
1. 正确模拟Supabase模块结构
Supabase的auth.signUp是异步方法,返回的是包含data和error属性的Promise对象。必须确保模拟的函数返回符合该结构的Promise,才能避免解构时出现undefined。
在测试文件中用jest.mock完整模拟@supabase/supabase-js模块,确保auth对象下的signUp是Jest mock函数:
// src/supabase/signUp.test.ts import { createClient } from '@supabase/supabase-js'; import { signUp } from './signUp'; // 模拟整个Supabase客户端模块 jest.mock('@supabase/supabase-js', () => ({ createClient: jest.fn(() => ({ auth: { signUp: jest.fn() // 定义mock的signUp方法 } })) })); // 获取mock的signUp函数,用于后续设置返回值 const mockSignUp = (createClient as jest.Mock).mockReturnValue().auth.signUp;
2. 针对不同测试用例动态设置返回值
使用mockResolvedValue(持久生效)或mockResolvedValueOnce(仅生效一次),为不同测试场景设置对应的返回对象,完美解决普通函数模拟无法动态修改返回值的问题。
测试成功场景
test('signUp成功时返回用户数据', async () => { // 设置mock返回成功数据 mockSignUp.mockResolvedValue({ data: { user: { id: '123', email: 'test@example.com' }, session: null }, error: null }); const result = await signUp('test@example.com', 'password123'); expect(result).toEqual({ user: { id: '123', email: 'test@example.com' }, session: null }); expect(mockSignUp).toHaveBeenCalledWith({ email: 'test@example.com', password: 'password123' }); });
测试失败场景
test('signUp失败时返回错误信息', async () => { // 设置mock返回错误 mockSignUp.mockResolvedValue({ data: null, error: { message: '邮箱已被注册', code: 'auth/email-already-exists' } }); const result = await signUp('existing@example.com', 'password123'); expect(result).toBeNull(); expect(mockSignUp).toHaveBeenCalledWith({ email: 'existing@example.com', password: 'password123' }); });
3. 自定义封装函数示例(signUp.ts)
确保你的封装函数正确解构返回值:
// src/supabase/signUp.ts import { supabase } from './client'; // 假设此处是初始化的Supabase客户端 export async function signUp(email: string, password: string) { const { data, error } = await supabase.auth.signUp({ email, password }); if (error) { console.error(error); return null; } return data; }
关键注意点
- 必须保证mock的
signUp返回Promise包裹的包含data/error的对象,否则解构时会出现undefined。 - 若需要隔离测试用例的mock状态,可在每个测试用例前调用
mockSignUp.mockReset(),避免测试用例间的干扰。
内容的提问来源于stack exchange,提问作者HotFix
相关产品推荐
相关产品推荐

