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

如何Mock带then和catch块的Firebase认证函数并使用Jest测试?

错误原因

你的mock写法存在两处核心问题:

  • jest.mock中对signInWithEmailAndPassword的导出多套了一层无意义的箭头函数,导致调用signInWithEmailAndPassword(auth, email, password)之后返回的是mockSignIn函数本身,而非执行mockSignIn得到的Promise对象,自然不存在then方法
  • 你只定义了注册用的mockSignUp,没有定义登录用的mockSignIn函数
  • 登录逻辑是异步操作,测试用例没有等待异步执行完成,会导致断言提前触发
修复方案

第一步:修正mock定义

// 提前定义所有依赖的mock函数
const mockGetAuth = jest.fn();
// 登录mock,返回符合结构的Promise
const mockSignIn = jest.fn(() => 
  Promise.resolve({
    user: {
      uid: "fakeuid",
      email: "abc@gmail.com"
    }
  })
);
const mockSignUp = jest.fn(() => 
  Promise.resolve({
    user: {
      uid: "fakeuid"
    }
  })
);

// 修正导出规则,直接绑定mock函数,不要多套箭头函数
jest.mock('firebase/auth', () => ({
  getAuth: mockGetAuth,
  signInWithEmailAndPassword: mockSignIn,
  createUserWithEmailAndPassword: mockSignUp
}));

第二步:修正测试用例,处理异步逻辑

test('Login with Email and Password', async () => {
  const { result } = renderHook(() => useFirebaseAuth())
  const email = 'abc@gmail.com'
  const password = '123456'

  act(() => {
    result.current.loginWithEmailPassword(email, password)
  })

  // 等待所有微任务执行完成,保证then/catch逻辑执行完毕
  await Promise.resolve()

  // 可选:验证mock被正确调用
  expect(mockSignIn).toHaveBeenCalledWith(expect.anything(), email, password)
})
可选优化

你可以直接把loginWithEmailPassword函数的Promise返回,测试会更简洁:

const loginWithEmailPassword = (email: string, password: string) => {
  const auth = getAuth()
  // 向外返回Promise
  return signInWithEmailAndPassword(auth, email, password)
    .then((userCredential) => {
      const user = userCredential.user;
      // 原有业务逻辑
      return user
    }).catch((error) => {
      const errorCode = error.code;
      const errorMessage = error.message;
      // 按需处理错误后抛出
      throw error
    });
}

对应测试代码可简化为:

test('Login with Email and Password', async () => {
  const { result } = renderHook(() => useFirebaseAuth())
  const email = 'abc@gmail.com'
  const password = '123456'

  await act(async () => {
    await result.current.loginWithEmailPassword(email, password)
  })

  expect(mockSignIn).toHaveBeenCalledWith(expect.anything(), email, password)
})

内容的提问来源于stack exchange,提问作者ken

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 01:27:03