Get Firebase Error: No Firebase App '[DEFAULT]' has been created when using React-hooks-testing-library with jest

Get Firebase Error: No Firebase App '[DEFAULT]' has been created when using React-hooks-testing-library with jest

我在 React 中使用 Firebase 身份验证,并尝试使用 react-hooks-testing-library 对其进行测试。我写的代码正在运行。但是当我尝试使用 react-hooks-testing-library 进行测试时,我得到了这个错误:

FirebaseError: Firebase: No Firebase App '[DEFAULT]' has been created , call Firebase App.initializeApp() (app/no-app).

这是我的实际代码:

useAuth.tsx

const defaultValue = {
     .. some value here
}

const AuthContext = createContext(defaultValue)

const AuthContextProvider = (props) => {
    const auth = useFirebaseAuth()

    return (
        <AuthContext.Provider
            value={auth}
        >
            {props.children}
        </AuthContext.Provider>
    );
}

const useAuth = () => {
    return useContext(AuthContext)
}

// I will like to test the function and behaviour inside this hooks, useFirebaseAuth() here
export default function useFirebaseAuth() {

    const [user, setUser] = useState(null)

  
    const loginWithEmailPassword = (email: string, password: string) => {

        const auth = getAuth() // the error point to this line!!! 

        //this code I followed the Firebase docs    
        return signInWithEmailAndPassword(auth, email, password)
            .then(res => {

            }).catch(error => {

            })
    }

    const signUpWithEmailPassword = () => {

    }


    return {
        user,
        loginWithEmailPassword,
        signUpWithEmailPassword
    }

}

export { useAuth, AuthContextProvider }

这个钩子里面会有3个item,分别是user, loginWithEmailPassword, signUpWithEmailPassword

这是我的测试

useAuth.test.tsx

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

// Here I tried to mock the auth function of Firebase
jest.mock('firebase/app', () => {
    return {
        App: () => ({
            app: mockGetApp
        }),
        auth: () => ({
            signInWithEmailAndPassword: mockSignIn,
            createUserWithEmailAndPassword: mockSignUp
        })
    }
})

const mockInitializeFirebase = jest.fn()
const mockSignUp = jest.fn(() => Promise.resolve())
const mockSignIn = jest.fn(() => Promise.resolve())
const mockGetApp = jest.fn()

jest.mock('../../utils/initAuth', () => {
    return {
        app: mockInitializeFirebase
    }
})

describe('useAuth Hooks testing', () => {

    test('Login with Email and Password', () => {
        const { result } = renderHook(() => useFirebaseAuth())

        console.log(result)

        //arrange it, confirm the initial state 
        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'
        // here act
        act(() => {
            // The problem come from this line
            result.current.loginWithEmailPassword(email, password)
        })
        // here assert 
        expect(mockSignIn).toBeCalledWith(email, password)

    })
})

所以当我触发 loginWithEmailPassword(email,password) 函数时,它一直显示 No Firebase App error。但是在我的项目中我已经有了这个文件,它已经初始化了 Firebase 应用程序。

./initFirebase.tsx,这里已经初始化了app,并在index.tsx

中调用了
import { initializeApp, getApps, getApp } from "firebase/app";
import getEnvVars from '../environment'

const env = getEnvVars()

interface firebaseType {
    apiKey: string,
    authDomain: string,
    projectId: string,
    messagingSenderId: string
}

let firebaseConfig: firebaseType;

if (env !== null) {

    const { apiKey, authDomain, projectId, messagingSenderId } = env
    firebaseConfig = {
        apiKey: apiKey,
        authDomain: authDomain,
        projectId: projectId,
        messagingSenderId: messagingSenderId
    };
}

export const initFirebase = () => {
    if (getApps().length === 0) {
        initializeApp(firebaseConfig);
    } else {
        getApp()
    }
}

所以错误只发生在测试中,所以我想我应该模拟 initializeApp 函数并在测试中的某个地方调用它。但是我不知道该怎么做。

我刚刚开始 testing 领域。请有经验的朋友帮忙一下

这里是问题:

  1. 我的代码和测试发生了什么导致错误发生?

  2. 我应该怎么做才能解决这个错误?

提前谢谢你。

通过像这样模拟它解决了这个问题:

const mockSignUp = jest.fn(() => {
    return Promise.resolve({
        user: {
            uid: "fakeuid",
        },
    });
})
const mockSignIn = jest.fn(() => Promise.resolve({
    user: {
        uid: "fakeUid"
    }
}))

const mockGetAuth = jest.fn()

jest.mock('firebase/auth', () => {
    return {
        getAuth: () => mockGetAuth,
        signInWithEmailAndPassword: () => mockSignIn,
        createUserWithEmailAndPassword: () => mockSignUp
    }
})

据此注明:

getAuth: ()=> mockGetAuth 那里的 3 函数,这将在 firebase 中模拟为我定义的 mockGetAuth 函数的 getAuth()

然后在测试中我可以这样调用模拟函数:

// here check the mock function 
mockSignIn(mockGetAuth, email, password)
expect(mockSignIn).toBeCalledWith(mockGetAuth, email, password)