My Battle With Jest Mocks and Firebase Auth
Learn how a subtle mistake in mocking Firebase Auth with Jest caused hours of debugging — and the simple fix that made it all work. A must-read for React Native developers writing unit tests with external libraries.
Why is this mockResolvedValue not working?! That was me — staring at my terminal, debugging the same Jest test for the third hour in a row.
This is the story of how a small mistake in mocking @react-native-firebase/auth
cost me hours of testing frustration, and what I learned that finally fixed it.
The Setup
I was writing tests for a sign-up screen in a React Native app. The component uses Firebase Auth to create a new user:
import auth from '@react-native-firebase/auth';
const signUp = async (email: string, password: string) => {
const userCredential = await auth().createUserWithEmailAndPassword(email, password);
return userCredential.user;
};
Seems straightforward enough, right?
All I needed was to mock auth()
so I could control what createUserWithEmailAndPassword
returned in my tests.
So I wrote this:
jest.mock('@react-native-firebase/auth', () => {
return () => ({
createUserWithEmailAndPassword: jest.fn(),
});
});
In my test:
(auth().createUserWithEmailAndPassword as jest.Mock).mockResolvedValue({
user: { uid: 'abc123', email: 'test@example.com' }
});
I expected the test to pass. But instead…
💥 TypeError: Cannot read property 'mockResolvedValue' of undefined
Huh? That didn’t make sense. I was mocking the function… wasn’t I?
The Confusing Part
I tried console logging, debugging, even reading Firebase’s and Jest’s docs again.
It seemed like createUserWithEmailAndPassword
existed — but my test couldn't spy on it or set any return values.
After a lot of trial and error, I found this tiny difference that made all the difference:
✅ Working version:
const mockCreateUser = jest.fn();
jest.mock('@react-native-firebase/auth', () => {
return () => ({
createUserWithEmailAndPassword: mockCreateUser,
});
});
Boom. It worked. The test passed.
What Was Going Wrong?
In my original version, I did this:
createUserWithEmailAndPassword: jest.fn();
The problem? That creates a new mock function every time auth() is called.
So when I tried to modify the mock later with .mockResolvedValue(...)
, it had no effect — I was modifying a different instance than the one actually used.
But in the fixed version, I stored the mock function in a shared variable:
const mockCreateUser = jest.fn();
That way, every call to auth()
returns the same mock — and I can control it from my test.
Lesson Learned
This bug taught me a valuable (and slightly painful) lesson:
Always define your mock functions outside of your mock factory if you need to spy on or modify them.
It’s such a subtle thing, but crucial for mocking effectively — especially with dependencies that return functions like auth()
.
TL;DR
- ❌ Don’t inline your jest.fn() inside the returned object from jest.mock
- ✅ Do define it in a variable outside, and return that reference
- 🧠 Why? You need a shared reference so your test can modify it
Final Thoughts
This might seem like a small mistake, but it highlights how tricky mocking can get in real-world projects — especially with third-party SDKs.
If you're stuck on a Jest mock that “should work,” but doesn't — check if you’re accidentally recreating mocks every time.
Sometimes, the fix is just one const
away.