Jest模拟Firebase 9.0.0的onValue函数不生效,正确实现方式是什么?
问题根源
- 你创建的局部
firebase对象和组件实际导入的./Firebase模块没有关联,spy监听的是局部对象的方法,组件里调用的还是原模块的onValue,自然不会触发模拟逻辑 onValue的模拟实现逻辑错误:onValue接收2个参数(引用对象、快照回调),调用后会立即触发回调,返回值是取消订阅的函数。你之前的实现是调用onValue后返回了一个新函数,没有直接触发回调,自然不会执行setFeature更新状态
正确模拟方案
完整的测试代码如下:
import React from 'react' import Acerca from './Acerca' import { render } from 'react-dom' import { act } from 'react-dom/test-utils' // 导入模拟后的模块方法 import { onValue, ref } from './Firebase' // 模拟整个Firebase模块,所有导入的该模块都会被mock jest.mock('./Firebase', () => ({ db: {}, // 模拟空的db实例即可 ref: jest.fn(), // 模拟ref方法 onValue: jest.fn() })) let container beforeEach(() => { // 初始化挂载节点 container = document.createElement('div') document.body.appendChild(container) }) afterEach(() => { // 清理节点和mock状态 document.body.removeChild(container) container = null jest.clearAllMocks() }) it("Acerca -> displays title", async () => { // 按你的业务逻辑,feature节点的值为字符串"New feature" const mockFeatureVal = "New feature" const snapshot = { val: () => mockFeatureVal } // 模拟取消订阅函数 const mockUnsubscribe = jest.fn() // 修正onValue的模拟实现 onValue.mockImplementation((ref, callback) => { // 调用时直接触发快照回调,传入模拟数据 callback(snapshot) // 返回取消订阅函数 return mockUnsubscribe }) await act(async () => { render(<Acerca/>, container) }) // 验证结果 expect(onValue).toHaveBeenCalledTimes(1) expect(container.querySelector('h3').textContent).toBe(mockFeatureVal) expect(mockUnsubscribe).toBeDefined() // 可选:验证返回了取消订阅函数 })
补充说明
如果你的业务逻辑中feature节点存储的是对象结构,比如{title: "New feature"},只需要调整两个地方即可:
- 模拟
snapshot.val()的返回值:const snapshot = { val: () => ({ title: "New feature" }) } - 修改组件中渲染逻辑:
<h3>{feature.title}</h3>,避免直接渲染对象报错
内容的提问来源于stack exchange,提问作者Erik Martín Jordán
相关产品推荐
相关产品推荐

