You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Jest对Firebase Admin函数做单元测试并指定mock返回值

解决方案

问题核心原因

  • 你原先的mock对象没有正确替换实际导入的firebase-admin依赖,mock的链式调用结构不符合真实调用逻辑
  • admin.auth().createUser返回的是Promise对象,业务代码是异步逻辑,测试没有用async/await处理异步返回
  • 没有利用Jest提供的类型推导方法解决返回类型标注问题

正确实现步骤

1. 全局mock firebase-admin模块

在测试文件顶部导入依赖后直接mock整个模块,结构和真实调用对齐:

import * as admin from 'firebase-admin';
// 全局mock firebase-admin
jest.mock('firebase-admin', () => ({
  auth: jest.fn().mockReturnValue({
    createUser: jest.fn()
  })
}));

2. 改写测试用例

使用jest.mocked获得类型推导,自定义返回值,处理异步逻辑:

import { HttpException, HttpStatus } from '@nestjs/common';
import { AccountService } from './account.service';
import * as admin from 'firebase-admin';
import type { UserRecord } from 'firebase-admin/auth';

jest.mock('firebase-admin', () => ({
  auth: jest.fn().mockReturnValue({
    createUser: jest.fn()
  })
}));

// 获得带Firebase官方类型的mock方法
const mockCreateUser = jest.mocked(admin.auth().createUser);

describe('AccountService', () => {
  let service: AccountService;
  const mockRegisterDto = {
    email: 'test@test.com',
    password: '123456',
    displayName: 'test user'
  };
  const expectedAccount = {
    uid: 'mock-uid-123',
    email: 'test@test.com',
    emailVerified: false,
    displayName: 'test user',
    message: 'User is successfully registered!',
  };

  afterEach(() => {
    jest.clearAllMocks();
  });

  beforeEach(() => {
    service = new AccountService();
  });

  it('注册成功时返回正确的Account对象', async () => {
    // 自定义createUser的resolve值,类型完全匹配Firebase定义
    mockCreateUser.mockResolvedValue({
      uid: expectedAccount.uid,
      email: expectedAccount.email,
      emailVerified: expectedAccount.emailVerified,
      displayName: expectedAccount.displayName,
      disabled: false,
    } as UserRecord);

    const result = await service.registerUser(mockRegisterDto);
    expect(result).toEqual(expectedAccount);
    // 额外断言createUser调用参数符合预期
    expect(mockCreateUser).toHaveBeenCalledWith({
      email: mockRegisterDto.email,
      emailVerified: false,
      password: mockRegisterDto.password,
      displayName: mockRegisterDto.displayName,
      disabled: false,
    });
  });

  it('注册失败时抛出对应HttpException', async () => {
    const mockError = new Error('邮箱已被注册');
    mockCreateUser.mockRejectedValue(mockError);

    await expect(service.registerUser(mockRegisterDto)).rejects.toThrow(
      new HttpException(`Bad Request Error creating new user: ${mockError.message}`, HttpStatus.BAD_REQUEST)
    );
  });
});

内容的提问来源于stack exchange,提问作者Louw

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.08 06:15:02