用 Jest 模拟 Firebase 功能(单元测试)
Posted
技术标签:
【中文标题】用 Jest 模拟 Firebase 功能(单元测试)【英文标题】:Mocking Firebase function with Jest (Unit testing) 【发布时间】:2021-10-13 07:59:03 【问题描述】:我正在创建单元测试,但我可以找到一种方法来模拟 firebase 函数并在调用它们时指定返回类型。下面我发布了我想要模拟的内容(account.service.ts)以及我当前进行的测试。我想模拟并指定要使用 admin 返回的内容...(也就是设置 resp 对象值)。
以管理员身份从“firebase-admin”导入 *;
account.service.ts
const resp = admin
.auth()
.createUser(
email: registerDto.email,
emailVerified: false,
password: registerDto.password,
displayName: registerDto.displayName,
disabled: false,
)
.then(
(userCredential): Account => (
uid: userCredential.uid,
email: userCredential.email,
emailVerified: userCredential.emailVerified,
displayName: userCredential.displayName,
message: 'User is successfully registered!',
),
)
.catch((error) =>
// eslint-disable-next-line max-len
throw new HttpException(`$'Bad Request Error creating new user: '$error.message`, HttpStatus.BAD_REQUEST);
);
account.service.spec.ts
describe('61396089', () =>
afterEach(() =>
jest.restoreAllMocks();
);
const obj =
uid: 'uid',
email: 'email',
emailVerified: 'emailVerified',
displayName: 'displayName',
message: 'User is successfully registered!',
;
const jestAdminMock =
admin: () => (
auth: () => (
createUser: () => (
then: () => (
catch: () => obj,
),
),
),
),
;
it('should pass', () =>
const mockDataTable =
admin: jest.fn().mockReturnThis(),
auth: jest.fn().mockReturnThis(),
createUser: jest.fn().mockReturnThis(),
then: jest.fn().mockReturnThis(),
catch: jest.fn().mockReturnValueOnce(obj),
;
jest.spyOn(jestAdminMock, 'admin').mockImplementationOnce(() => mockDataTable);
const actual = service.registerUser(registerDTO);
expect(actual).toBe(obj);
);
);
);
【问题讨论】:
admin
对象从何而来?
以管理员身份从 'firebase-admin' 导入 *;
【参考方案1】:
我设法做了一个像这个例子这样的测试
这是函数
import admin from 'firebase-admin'
admin.initializeApp(
credential: admin.credential.cert(credentials),
)
const createClosure = (admin) =>
if (!admin)
throw new Error(Errors.FIREBASE_ADMIN_SDK_NOT_PROVIDED)
return (data) =>
if (
data &&
!Array.isArray(data) &&
typeof data === 'object' &&
Object.keys(data).length > 0
)
const firstName, lastName = data
const displayName = `$firstName $lastName`
return admin.auth().createUser( ...data, displayName )
throw new Error(Errors.INVALID_DATA)
/*
.....
*/
const create = createClosure(admin)
export create, createClosure
这是一个测试示例
import createClosure from "../path/to/function"
describe('createClosure', () =>
it('should be a function', () =>
expect(typeof createClosure).toBe('function')
)
describe('when admin is not provided', () =>
it('should throw "Firebase Admin SDK not provided"', () =>
const expected = Errors.FIREBASE_ADMIN_SDK_NOT_PROVIDED
expect(() => createClosure()).toThrow(expected)
)
)
describe('when admin is provided', () =>
describe('when data is invalid', () =>
const createUser = jest.fn()
const admin =
auth: () => (
createUser,
),
const data1 = 123
const data2 = 'hello'
const data3 = ['a', 'b', 'c']
const data4 =
it('should throw "Invalid data"', () =>
expect(() => createClosure(admin)()).toThrow(Errors.INVALID_DATA)
expect(() => createClosure(admin)(data1)).toThrow(Errors.INVALID_DATA)
expect(() => createClosure(admin)(data2)).toThrow(Errors.INVALID_DATA)
expect(() => createClosure(admin)(data3)).toThrow(Errors.INVALID_DATA)
expect(() => createClosure(admin)(data4)).toThrow(Errors.INVALID_DATA)
)
)
describe('when data is valid', () =>
const data =
firstName: 'Alice',
lastName: 'Alley',
foo: 'bar',
baz:
boo: 'bii',
buu: 'byy',
,
describe('when createUser rejects', () =>
const e = new Error('Error happened!')
const createUser = jest.fn().mockRejectedValue(e)
const admin =
auth: () => (
createUser,
),
const create = createClosure(admin)
it('should call createUser once', async () =>
try
await createUser(data)
catch (error)
expect(createUser).toBeCalledTimes(1)
expect(createUser).toBeCalledWith( ...data )
)
it('should reject', async () =>
await expect(create(data)).rejects.toEqual(e)
)
)
describe('when save resolves', () =>
const expected =
baz: boo: 'bii', buu: 'byy' ,
displayName: 'Alice Alley',
lastName: 'Alley',
const displayName = `$data.firstName $data.lastName`
const createUser = jest.fn().mockResolvedValue(expected)
const admin =
auth: () => (
createUser,
),
const create = createClosure(admin)
it('should call save once', async () =>
try
await create(data)
catch (error)
expect(createUser).toBeCalledTimes(1)
expect(createUser).toBeCalledWith( ...data, displayName )
)
it('should resolve', async () =>
const result = await create(data)
expect(result).toMatchObject(expected)
)
)
)
)
)
【讨论】:
非常感谢。我将使用它作为参考,看看我是否可以运行我的测试。如果我设法解决测试,我将关闭问题。以上是关于用 Jest 模拟 Firebase 功能(单元测试)的主要内容,如果未能解决你的问题,请参考以下文章
用 Jest 反应单元测试 - 模拟 localStorage 的问题