如何使用Firebase Emulators配合Jest测试使用Firebase的React应用
你操作的问题主要有两个:
initializeTestApp返回的测试用Firebase实例没有被你的App组件使用,App内部直接调用了全局firebase对象的storage方法,而你没有初始化全局默认的[DEFAULT] Firebase实例,因此触发报错。- 组件顶层直接调用异步的
getDownloadURL方法,测试时没有等待异步逻辑执行完成就生成快照,即使解决了实例问题也拿不到预期的渲染结果。
解决步骤
- 首先修改App组件,支持传入Firebase实例,同时把异步逻辑放到useEffect中避免重复触发请求:
import firebase from "firebase/app"; import 'firebase/storage' import React, {useState, useEffect} from 'react' // 支持外部传入firebase实例,默认使用全局实例 export default ({firebaseApp = firebase})=>{ const [url, setUrl] = useState<null | string>(null) useEffect(() => { let isMounted = true firebaseApp .storage() .ref('path/file') .getDownloadURL() .then((v) => { if (isMounted) setUrl(v); }) return () => {isMounted = false} }, [firebaseApp]) return <div> {url} </div> }
- 接着修改测试代码,将初始化好的测试实例传入组件,同时等待异步逻辑执行完成再生成快照:
import {initializeTestApp, useEmulators} from '@firebase/rules-unit-testing' import { render, waitFor } from '@testing-library/react' import App from '../App' useEmulators({ storage:{ host: 'localhost', port: 9199 } }) // 保存初始化完成的测试用Firebase实例 const testApp = initializeTestApp({ storageBucket: "my-bucket", auth: { uid: "alice" } }) describe('test', ()=>{ it('can match snapshot', async () => { const { baseElement } = render( // 传入测试实例 <App firebaseApp={testApp}/> ); // 等待异步请求完成、内容渲染完成 await waitFor(() => { expect(baseElement.textContent).not.toBeEmpty() }) expect(baseElement).toMatchSnapshot(); }) })
如果你不想修改App组件的入参,也可以在测试文件中mock firebase/app的导出,让它直接返回你初始化好的testApp,同样可以解决实例不匹配的问题。
内容的提问来源于stack exchange,提问作者Simon Tran
相关产品推荐
相关产品推荐

