Node.js中Supabase API Select请求Mock失败问题排查
问题:Jest Mock Supabase后调用userPermissions返回data和error均为undefined
在Express.js后端使用Supabase,已完成Supabase Client定义,通过链式方法构建Query并执行数据库调用。编写Jest测试时Mock了Supabase,但调用userPermissions方法时,Supabase返回的data和error均为undefined,无法获取Mock中定义的返回值。
相关代码
Supabase Client定义
const config = require('../config/env'); const supabase = require('@supabase/supabase-js'); const supabaseClient = supabase.createClient( config.supabase.url, config.supabase.key, { auth: { autoRefreshToken: false, persistSession: false, detectSessionInUrl: false, }, } ); module.exports = supabaseClient;
数据库调用示例
const query = supabaseClient .from('items') .select('*') .eq('id', id); const { data, error } = await executeWithRetry(async () => await query);
Jest Mock代码
jest.mock('@supabase/supabase-js', () => { return { createClient: jest.fn().mockImplementation(() => { return { from: jest.fn().mockReturnThis(), select: jest.fn().mockImplementation(() => ({ eq: jest.fn().mockReturnThis(), in: jest.fn().mockReturnThis(), is: jest.fn().mockReturnThis(), order: jest.fn().mockReturnThis(), gte: jest.fn().mockReturnThis(), lte: jest.fn().mockReturnThis(), execute: jest.fn().mockImplementation(() => { return Promise.resolve({ data: [{ id: 'some-uuid-text' }], error: null, }); }), }), }; }), }; });
测试代码
describe('userPermissions', () => { it('should fetch user permissions', async () => { const email = 'test@example.com'; const result = await userPermissions({ email }); expect(result).toEqual([{ role_id: 'mockedRoleId' }]); }); });
问题原因
- 链式调用上下文断裂:Mock中
select方法返回了全新对象,而非通过mockReturnThis()维持原上下文一致性。Supabase原生链式调用中,from/select/eq等方法均返回同一个Query实例,你的Mock破坏了这个链式结构。 - 未模拟Query的可await特性:实际代码中直接
await query,意味着Query实例需要是Promise或实现then方法。你的Mock仅给最后返回的对象添加了execute方法,但代码并未调用execute(),而是直接await Query实例,导致无返回值。
修复方案
调整Jest Mock,确保链式调用上下文一致,同时让Query实例支持直接await:
jest.mock('@supabase/supabase-js', () => { // 定义统一的mock query对象,支持链式调用和await const mockQuery = { from: jest.fn().mockReturnThis(), select: jest.fn().mockReturnThis(), eq: jest.fn().mockReturnThis(), in: jest.fn().mockReturnThis(), is: jest.fn().mockReturnThis(), order: jest.fn().mockReturnThis(), gte: jest.fn().mockReturnThis(), lte: jest.fn().mockReturnThis(), // 实现then方法,模拟Promise行为,支持直接await query then: jest.fn((resolve) => { resolve({ data: [{ role_id: 'mockedRoleId' }], error: null, }); }), // 保留execute方法,兼容可能存在的显式调用场景 execute: jest.fn().mockResolvedValue({ data: [{ role_id: 'mockedRoleId' }], error: null, }), }; return { createClient: jest.fn().mockReturnValue(mockQuery), }; });
关键说明
- 所有链式方法均通过
mockReturnThis()返回同一个mockQuery对象,维持上下文一致性。 - 添加
then方法模拟Promise行为,让直接await query能返回预设的data和error。 - 同时保留
execute方法的mock,兼容代码中可能存在的显式调用query.execute()的场景。
内容的提问来源于stack exchange,提问作者John Mboga
相关产品推荐
相关产品推荐

