My Battle With Jest Mocks and Firebase Auth

#Testing#Jest#React Native#Firebase#JavaScript

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.