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

使用react-hooks-testing-library测试Firebase auth报无默认App错误如何解决

问题原因
  • 你当前对Firebase的mock完全不匹配代码中使用的模块化API:你代码中实际使用的是v9+版本的模块化API(getAuth()、signInWithEmailAndPassword、initializeApp等直接从对应包导入的方法),但你mock的是v8及之前的链式调用结构,没有覆盖实际用到的方法,导致getAuth执行时调用了真实的Firebase逻辑,检测不到初始化的App实例就抛出错误。
  • 测试运行环境不会执行业务入口index.tsx的初始化逻辑:你业务中虽然在入口调用了initFirebase,但单测运行时只会执行测试文件和被测试文件的代码,没有触发初始化逻辑,即使不mock的情况下也会缺少App实例。
  • 断言逻辑存在问题:signInWithEmailAndPassword的第一个参数是auth实例,之后才是邮箱和密码,你当前的断言参数匹配错误,且loginWithEmailPassword是异步方法,你没有等待Promise执行完成就做断言,会出现断言时序错误。
解决方法

你需要把所有用到的Firebase API都正确mock,修改后的测试代码参考如下:

import React from 'react'
import { renderHook, act } from '@testing-library/react-hooks/native'
import useFirebaseAuth from '../useAuth';

// 先定义mock方法
const mockSignIn = jest.fn(() => Promise.resolve({ user: { uid: 'test-uid' } }))
const mockGetAuth = jest.fn(() => ({})) // mock getAuth直接返回空对象即可

//  mock firebase/auth模块,覆盖你用到的方法
jest.mock('firebase/auth', () => ({
  getAuth: mockGetAuth,
  signInWithEmailAndPassword: mockSignIn
}))

// mock firebase/app模块的初始化相关方法
jest.mock('firebase/app', () => ({
  initializeApp: jest.fn(),
  getApps: jest.fn(() => [{}]), // 模拟已经有初始化的App
  getApp: jest.fn(() => ({}))
}))

// 对应mock你自己的初始化文件
jest.mock('../../utils/initAuth', () => ({
  initFirebase: jest.fn()
}))

describe('useAuth Hooks testing', () => {
  // 每次测试前清空mock调用记录
  beforeEach(() => {
    jest.clearAllMocks()
  })

  test('Login with Email and Password', async () => { // 加async处理异步
    const { result } = renderHook(() => useFirebaseAuth())

    // 初始状态断言
    expect(result.current.user).toBe(null)
    expect(typeof result.current.loginWithEmailPassword).toBe('function')
    expect(typeof result.current.signUpWithEmailPassword).toBe('function')

    const email = 'abc@gmail.com'
    const password = '123456'
    
    // 等待异步方法执行完成
    await act(async () => {
      await result.current.loginWithEmailPassword(email, password)
    })

    // 修正断言参数,第一个参数是getAuth返回的auth实例,之后是邮箱密码
    expect(mockSignIn).toBeCalledWith({}, email, password)
    expect(mockGetAuth).toBeCalledTimes(1)
  })
})

如果需要测试注册逻辑,只需要在firebase/auth的mock里加上对应的createUserWithEmailAndPassword和对应的mock方法即可。

内容的提问来源于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:09:02