Reputation: 2672
I using Firebase auth in React, and I try to test it with react-hooks-testing-library
. The code I write is working. But when I try to test with react-hooks-testing-library
I get this error:
FirebaseError: Firebase: No Firebase App '[DEFAULT]' has been created , call Firebase App.initializeApp() (app/no-app).
Here is my actual code:
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 }
Inside this hook will have 3 item, which user
, loginWithEmailPassword
, signUpWithEmailPassword
Here is my test
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 = '[email protected]'
const password = '123456'
// here act
act(() => {
// The problem come from this line
result.current.loginWithEmailPassword(email, password)
})
// here assert
expect(mockSignIn).toBeCalledWith(email, password)
})
})
So when I fired the loginWithEmailPassword(email,password)
function, it keep showing No Firebase App error
. But in my project I already have this file, which is initialize the Firebase app already.
./initFirebase.tsx, here already initialize the app, and called it in 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()
}
}
So the error is only happened in test, so I think I should mock the initializeApp
function and call it somewhere in the test. But I dont know how to do that.
I just get started in testing
field. Somebody that have experience please give some help.
Here is the question:
What happened to my code and test that make the error occured?
What should I do in order to solve this error?
Thank you in advance.
Upvotes: 1
Views: 842
Reputation: 2672
Solved this by mock it like this:
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
}
})
Noted by this:
getAuth: ()=> mockGetAuth
the 3 function there, this will mock as getAuth()
in firebase to the mockGetAuth function I defined.
Then in test I can called the mock function like this:
// here check the mock function
mockSignIn(mockGetAuth, email, password)
expect(mockSignIn).toBeCalledWith(mockGetAuth, email, password)
Upvotes: 1