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

ReactJS中如何在Jest测试用例中使用Firebase模拟器?

问题:如何在Jest测试中使用Firebase模拟器获取数据?

我已经成功搭建Firebase模拟器,但不清楚如何在Jest测试用例中从模拟器存储获取数据,尝试实现后出现错误。以下是我的测试文件与Redux动作代码,恳请指导:

user.test.js

import { firestore } from 'firebase-admin';
import { collection, doc } from 'firebase/firestore';

import { initializeTestApp, loadFirestoreRules } from '@firebase/rules-unit-testing';
import { setUserData, companyRef, stored, company, product } from '../mock';import userSlice, {
  hasError,
  initialState,
  resetStateData,
  setUser,
} from '../src/redux/slices/user';

beforeAll(async () => {
  await loadFirestoreRules({ projectId, rules: '../firestore.rules' });
});

afterAll(async () => {
  await app.delete();
});

const mockStore = configureMockStore();

const store = mockStore(stored);

describe('User test case :-', () => {
  const error = { status: '401', message: 'Something went to wrong' };
  const userId = 'VOmxX13c7ygUhOmzXZefXfnLLwZ2';
  const otherUserData = setUserData;
  const companyRefMock = companyRef;
  const dispatch = jest.fn();

  beforeEach(async () => {
    // Set up necessary data before each test
    // You can create documents in the Firestore emulator using 'setDoc'
    await setDoc(doc(collection(db, 'users'), '5e86809283e28b96d2d38537'), {
      /* user data */
    });
    await setDoc(doc(collection(db, 'super-user'), '5e86809283e28b96d2d38537'), {
      /* super user data */
    });
  });

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

  // Test of Success for updateUser
  test('setUser action should set user profile data correctly', async () => {
    const snapshot = await firestore.collection('your_collection').get();

    // const snapshot = await jest.mock(firestore.collection('user').get());
    console.log('snapshot', snapshot);
    await dispatch(setUser(userId, otherUserData));
    // check loading state
    expect(dispatch).toBeCalled(dispatch(userLoading()));
    // check setAuthentication state
    expect(dispatch).toBeCalled(dispatch(setAuthentication(true)));
    expect(dispatch).toBeCalled(dispatch(hasError(error)));

    // Compare with the store
    expect(store.getState().isUserLoading).toBe(false);
    expect(store.getState().isAuthenticated).toBe(true);
    expect(store.getState().error).toEqual(error);
  });
});

user.js(Redux动作)

export function setUser(userId, otherUserData) {
  return async (dispatch) => {
    dispatch(slice.actions.userLoading(true));
    try {
      const userRef = doc(DB, 'users', userId);
      const userDocumentSnap = await getDoc(userRef);
      const docSuperUserRef = await doc(collection(DB, 'super-user'), userId);
      const docSuperUserSnapshot = await getDoc(docSuperUserRef);
      const isSuperUser = docSuperUserSnapshot.exists();
      let userProfile = userDocumentSnap.data();
      if (otherUserData) {
        userProfile = { ...otherUserData, ...userProfile, isSuperUser };
      }
      if (isSuperUser) {
        dispatch(getAllCompanies());
      }
      dispatch(slice.actions.setUserSuccess({ userProfile, userRef }));
      dispatch(setUserInvitations(userProfile));
      dispatch(setAllProducts());

      if (userProfile.companies) {
        dispatch(slice.actions.setCompanies(userProfile.companies));
      }
      dispatch(slice.actions.setAuthentication(true));
    } catch (error) {
// console.error(error);

      dispatch(slice.actions.hasError(error));
      dispatch(slice.actions.setAuthentication(false));
    } finally {
      dispatch(slice.actions.userLoading(false));
    }
  };
}

解决方案

1. 修正测试环境初始化逻辑

你的测试代码未正确初始化Firebase测试应用和Firestore实例,需补充如下:

import { firestore } from 'firebase-admin';
import { collection, doc, setDoc, getDoc } from 'firebase/firestore';
import { initializeTestApp, loadFirestoreRules, clearFirestoreData } from '@firebase/rules-unit-testing';
import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';
// 补充缺失的action导入
import { userLoading, setAuthentication } from '../src/redux/slices/user';

const projectId = 'test-project-id'; // 自定义测试项目ID
let app;
let db;

beforeAll(async () => {
  // 初始化测试应用
  app = initializeTestApp({ projectId });
  db = firestore(app);
  // 加载Firestore规则
  await loadFirestoreRules({ projectId, rules: '../firestore.rules' });
});

afterAll(async () => {
  // 清理测试数据,避免用例间污染
  await clearFirestoreData({ projectId });
  await app.delete();
});

// 配置mock store,添加thunk中间件支持异步action
const mockStore = configureMockStore([thunk]);

2. 完善测试数据准备

beforeEach中需使用初始化好的db实例,且填充与测试用例匹配的真实数据:

beforeEach(async () => {
  const testUserId = 'VOmxX13c7ygUhOmzXZefXfnLLwZ2'; // 与测试用例的userId保持一致
  // 创建普通用户数据
  await setDoc(doc(db, 'users', testUserId), {
    name: 'Test User',
    email: 'test@example.com',
    companies: ['company1']
  });
  // 创建超级用户数据(若需测试超级用户分支)
  await setDoc(doc(db, 'super-user', testUserId), {
    role: 'super'
  });
});

3. 修正测试用例逻辑

移除无效代码,使用mock store测试异步action的正确行为:

test('setUser action should set user profile data correctly', async () => {
  const userId = 'VOmxX13c7ygUhOmzXZefXfnLLwZ2';
  const otherUserData = { nickname: 'Nick' };
  
  const store = mockStore(initialState);
  
  await store.dispatch(setUser(userId, otherUserData));
  
  const actions = store.getActions();
  
  // 断言loading状态变化
  expect(actions).toContainEqual(userLoading(true));
  expect(actions).toContainEqual(userLoading(false));
  
  // 断言认证状态设置成功
  expect(actions).toContainEqual(setAuthentication(true));
  
  // 断言无错误触发
  expect(actions.some(action => action.type === userSlice.actions.hasError.type)).toBe(false);
  
  // 断言用户数据正确合并
  const setUserSuccessAction = actions.find(action => action.type === userSlice.actions.setUserSuccess.type);
  expect(setUserSuccessAction.payload.userProfile).toEqual(expect.objectContaining({
    name: 'Test User',
    nickname: 'Nick',
    isSuperUser: true
  }));
});

4. 确保Redux中的Firestore指向模拟器

在Firestore初始化文件中添加测试环境判断,强制连接到模拟器:

import { initializeApp } from 'firebase/app';
import { getFirestore, connectFirestoreEmulator } from 'firebase/firestore';

const firebaseConfig = { /* 你的Firebase配置 */ };

const app = initializeApp(firebaseConfig);
const DB = getFirestore(app);

// 测试环境下连接到模拟器
if (process.env.NODE_ENV === 'test') {
  connectFirestoreEmulator(DB, 'localhost', 8080);
}

export { DB };

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 01:28:10