You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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' }]);
  });
});

问题原因

  1. 链式调用上下文断裂:Mock中select方法返回了全新对象,而非通过mockReturnThis()维持原上下文一致性。Supabase原生链式调用中,from/select/eq等方法均返回同一个Query实例,你的Mock破坏了这个链式结构。
  2. 未模拟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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 09:25:32