Reputation: 4627
I am hopelessly trying to mock firebase admin dependency in typescript for unit testing.
My actual function is as below
import {auth} from 'firebase-admin';
async validateUser(payload: string): Promise<User> {
try {
const resp = await auth().verifyIdToken(payload, true);
return await this.userService.findByUsername(resp.email);
} catch (e) {
return null;
}
}
I am trying to test the admin.auth().verifyIdToken(payload, true)
by mocking the admin
function. I attempted the test code like below
import {auth} from 'firebase-admin';
jest.mock('firebase-admin');
const mockedAuth = auth as jest.Mock;
mockedAuth.mockReturnValue({
verifyIdToken: jest.fn().mockResolvedValue(true),
});
but I get an error saying TypeError: Cannot read property 'mockReturnValue' of undefined
if I am understanding correctly, I am mocking the entire firebase-admin
package by calling jest.mock('firebase-admin')
. So I would expect to be able to call mockReturnValue
and again mock the verifyIdToken
function within the auth function. However, I am not even able to call mockReturnValue
because weirdly it doesn't seem to exist.
How do I need to write a code so that I can mock the resolved value from auth().verifyIdToken()
?
Upvotes: 2
Views: 7539
Reputation: 16157
Use jest mock factory to mock firebase
module.
jest.mock('firebase-admin', () => {
return {
auth: jest.fn(),
}
});
Example for spec file:
import { auth } from 'firebase-admin';
import Test from './index';
jest.mock('firebase-admin', () => {
return {
auth: jest.fn(),
}
});
describe("Test", () => {
const email = '[email protected]';
const user = { email, username: 'mocked-username' };
let mockedAuth: jest.Mock;
let mockVerifyIdToken: jest.Mock;
let mockUserService: { findByUsername: jest.Mock }; // mock userService
let testInstance: Test;
beforeEach(() => {
mockedAuth = auth as jest.Mock;
mockVerifyIdToken = jest.fn()
mockedAuth.mockReturnValue({
verifyIdToken: mockVerifyIdToken,
});
mockUserService = {
findByUsername: jest.fn(),
};
testInstance = new Test(mockUserService);
});
test("should return user info when pass correct payload", async () => {
const payload = 'mocked-payload';
mockVerifyIdToken.mockResolvedValue({ email });
mockUserService.findByUsername.mockResolvedValue(user);
const result = await testInstance.validateUser(payload);
expect(result).toBe(user);
expect(mockVerifyIdToken).toHaveBeenCalledWith(payload, true);
expect(mockUserService.findByUsername).toHaveBeenCalledWith(email);
});
})
Upvotes: 3
Reputation: 2099
The trouble in this case is that auth
and similar exported functions in firebase-admin
are defined as getters with Object.defineProperty
. Unfortunately jest.mock
can't see those when it evaluates the module, so it doesn't add mocks for them.
You'll need to mock auth
(and any sibling functions you need) in a factory provided to jest.mock
. Here's how, replacing the jest.mock
line in your second code snippet:
jest.mock('firebase-admin', () =>
{
const module = jest.createMockFromModule<any>('firebase-admin').default;
module.auth = jest.fn();
return module;
});
You could also choose to mock auth
's return value within that factory to further streamline your code.
Upvotes: 2