0

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

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

这是我的实际代码:

使用Auth.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 个项目,其中user, loginWithEmailPassword,signUpWithEmailPassword

这是我的测试

使用Auth.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,这里已经初始化了应用程序,并调用了它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. 我应该怎么做才能解决这个错误?

先感谢您。

4

1 回答 1

0

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

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 函数,这将像getAuth()在 firebase 中模拟到我定义的 mockGetAuth 函数一样。

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

// here check the mock function 
mockSignIn(mockGetAuth, email, password)
expect(mockSignIn).toBeCalledWith(mockGetAuth, email, password)
于 2021-09-01T16:50:24.073 回答