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,提问作者Екатерина
相关产品推荐
相关产品推荐

