我绝望地试图在 typescript 中模拟 firebase 管理依赖以进行单元测试。
我的实际功能如下
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;
}
}
我试图通过模拟 admin.auth().verifyIdToken(payload, true)
函数来测试 admin
。我尝试了如下测试代码
import {auth} from 'firebase-admin';
jest.mock('firebase-admin');
const mockedAuth = auth as jest.Mock;
mockedAuth.mockReturnValue({
verifyIdToken: jest.fn().mockResolvedValue(true),
});
但我收到一条错误消息 TypeError: Cannot read property 'mockReturnValue' of undefined
如果我理解正确,我就是通过调用 firebase-admin
来模拟整个 jest.mock('firebase-admin')
包。所以我希望能够在 auth 函数中调用 mockReturnValue
并再次模拟 verifyIdToken
函数。但是,我什至无法调用 mockReturnValue
,因为奇怪的是它似乎不存在。
我需要如何编写代码才能模拟来自 auth().verifyIdToken()
的解析值?
答案 0 :(得分:1)
这种情况下的麻烦在于 auth
和 firebase-admin
中类似的导出函数被定义为带有 Object.defineProperty
的 getter。不幸的是,jest.mock
在评估模块时看不到这些,因此它不会为它们添加模拟。
您需要在提供给 auth
的工厂中模拟 jest.mock
(以及您需要的任何同级函数)。以下是替换第二个代码段中的 jest.mock
行的方法:
jest.mock('firebase-admin', () =>
{
const module = jest.createMockFromModule<any>('firebase-admin').default;
module.auth = jest.fn();
return module;
});
您还可以选择在该工厂中模拟 auth
的返回值,以进一步简化您的代码。
答案 1 :(得分:1)
用户玩笑模拟工厂来模拟 firebase
模块。
jest.mock('firebase-admin', () => {
return {
auth: jest.fn(),
}
});
规范文件示例:
import { auth } from 'firebase-admin';
import Test from './index';
jest.mock('firebase-admin', () => {
return {
auth: jest.fn(),
}
});
describe("Test", () => {
const email = 'mocked-email@example.com';
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);
});
})