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

Redux Toolkit异步Thunk中Mock Firebase方法返回Undefined问题排查

问题原因及修正方案

你当前的Mock写法存在两处关键错误,导致返回值不符合预期:

1. Mock函数的暴露方式错误

在jest.mock的工厂函数中,你把addDoc和createUserWithEmailAndPassword定义成了返回mock函数的函数,而不是直接暴露mock函数本身。

比如原代码里:

jest.mock('firebase/firestore', () => ({
  ...jest.requireActual('firebase/firestore'),
  addDoc: () => mockedAddDoc, // 错误:返回的是一个函数,这个函数返回mock函数
}));

当你的Thunk调用addDoc()时,实际得到的是mockedAddDoc这个函数,而非它执行后返回的Promise。await这个函数的结果自然是undefined,解构doc.id就会出错。

修正:直接将mock函数赋值给对应的Firebase方法:

jest.mock('firebase/firestore', () => ({
  ...jest.requireActual('firebase/firestore'),
  addDoc: mockedAddDoc, // 直接暴露mock函数
}));

jest.mock('firebase/auth', () => ({
  ...jest.requireActual('firebase/auth'),
  createUserWithEmailAndPassword: mockedСreateUserWithEmailAndPassword, // 同理修正
}));

2. mockedAddDoc的返回值不符合代码预期

你的Thunk中需要从addDoc的返回值取doc.id,但原Mock的返回值是Promise.resolve({ doc: {id: '333'} }),这会导致doc.id实际是undefined(因为返回的对象里没有id属性,只有嵌套的doc.id)。

修正:让mockedAddDoc直接返回包含id的对象:

const mockedAddDoc = jest.fn();
mockedAddDoc.mockImplementation(() => Promise.resolve({ id: '333' })); // 直接返回id属性

修正后的完整测试代码

import {registerUser} from '../slices/userSlice';

const mockedСreateUserWithEmailAndPassword = jest.fn();
mockedСreateUserWithEmailAndPassword.mockImplementationOnce(() => Promise.resolve({ user: { refreshToken: '123', uid: '321' } }));

const mockedAddDoc = jest.fn();
mockedAddDoc.mockImplementation(() => Promise.resolve({ id: '333' })); // 修正返回值

jest.mock('firebase/firestore', () => ({
  ...jest.requireActual('firebase/firestore'),
  addDoc: mockedAddDoc, // 直接赋值mock函数
}));

jest.mock('firebase/auth', () => ({
  ...jest.requireActual('firebase/auth'),
  createUserWithEmailAndPassword: mockedСreateUserWithEmailAndPassword, // 直接赋值mock函数
}));

describe('registerUser thunk', () => {
  it('should register user with resolved response', async () => {
    const dispatch = jest.fn();
    const thunk = registerUser({ 
      name: 'TestName', 
      surname: 'TestSurname', 
      email: 'test@test.com', 
      password: 'testPassword' 
    });

    await thunk(dispatch, () => {}, () => {});
    const [pendingCall, fulfilledCall] = dispatch.mock.calls;
    expect(fulfilledCall[0].type).toBe('user/registerUser/fulfilled'); // 修正调用顺序:第一个是pending,第二个才是fulfilled
  })
})

内容的提问来源于stack exchange,提问作者Екатерина

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 19:05:21