如何测试基于 Firebase 方法的自定义 React 查询挂钩?
How to test custom React-query hook that is based on Firebase methods?
我遇到了 react-query-firebase,它们是基于 React-query for firebase 构建的钩子。
我还找到了名为 mock service worker 的库 https://mswjs.io/,但它基于 REST 和 GraphQL。
这是我如何使用这些钩子的示例代码:
import React from "react";
import { useFirestoreDocument } from "@react-query-firebase/firestore";
import {
doc
} from "firebase/firestore";
import { firestore } from "../firebase";
function GetUser() {
const id = "pW5CizOJOpXezr5lGGshDmKdVpP3";
const ref = doc(firestore, "users", id);
const user = useFirestoreDocument(["users", id], ref);
return (
<div>
{user.isLoading && <div>Loading...</div>}
{user.data && <div>{user.data.data()?.name}</div>}
</div>
);
}
export default GetUser;
我是测试的新手,我不知道我必须如何执行这个测试,因为我在模拟请求,我可以使用随机 url 还是必须是 firebase 相关的方法?
react-query-firebase 库是对 Firebase 的抽象,它封装了资源路径(我相信它是一个 SDK)。由于路径 (URL) 是从中抽象出来的,因此对于如何模拟此类库发出的请求,您至少有两种选择。
选项 1:使用显式路径
虽然隐藏了确切的资源路径,请求仍然引用现有的绝对路径。您可以在浏览器的“网络”选项卡中观察这些内容,或者通过使用 msw
:
启用简单的请求自省
// my.test.js
import { setupServer } from 'msw/node'
const server = setupServer(/* no handlers */)
beforeAll(() => server.listen())
afterAll(() => server.close())
Since we're using setupServer
with no handlers, all requests that happen in my.test.js
will be printed as warnings to stderr
. You can observe those warnings to see what resource paths your SDK requests.
使用 SDK 的好处是它可以保证您有一定的资源路径结构。最有可能的是,您将能够在模拟中复制该结构:
// src/mocks.js
import { rest } from 'msw'
export const handlers = [
rest.get('https://some-resource.:checksum.firebase.app/path', (req, res, ctx) => res(ctx.text('hello)))
]
Utilize dynamic path segments like :checksum
to match a broader range of paths.
这种方法的缺点是您的模拟定义变得依赖于 SDK 内部细节(资源路径)。对 SDK 的任何更新都可能破坏您的模拟,因为它们可能会在内部更新路径结构而不将其表示为重大更改(抽象路径不是 public API)。
选项 2:监视 SDK
或者,您可以监视正在使用的 SDK。这种间谍的一个例子是直接在 react-query-firebase
上使用 jest.spyOn
:
// my.test.js
import * as reactQueryFirebase from 'react-query-firebase'
it('creates a user', () => {
jest.spyOn(reactQueryFirebase, 'SOME_METHOD_NAME')
.mockReturnValue(/* mock */)
})
此方法的缺点是您从第三方库中存根函数,这意味着您的测试代码永远不会调用这些函数。这会降低此类测试的可靠性,通常情况下,您应该避免采用这种方法。
我确实建议您研究 Firebase,因为主要的 SDK 提供商通常有关于模拟其 API 的指南。通常这样的指导会包括使用由 SDK 提供商编写的专用第三方包,允许模拟其内部资源。
我遇到了 react-query-firebase,它们是基于 React-query for firebase 构建的钩子。
我还找到了名为 mock service worker 的库 https://mswjs.io/,但它基于 REST 和 GraphQL。
这是我如何使用这些钩子的示例代码:
import React from "react";
import { useFirestoreDocument } from "@react-query-firebase/firestore";
import {
doc
} from "firebase/firestore";
import { firestore } from "../firebase";
function GetUser() {
const id = "pW5CizOJOpXezr5lGGshDmKdVpP3";
const ref = doc(firestore, "users", id);
const user = useFirestoreDocument(["users", id], ref);
return (
<div>
{user.isLoading && <div>Loading...</div>}
{user.data && <div>{user.data.data()?.name}</div>}
</div>
);
}
export default GetUser;
我是测试的新手,我不知道我必须如何执行这个测试,因为我在模拟请求,我可以使用随机 url 还是必须是 firebase 相关的方法?
react-query-firebase 库是对 Firebase 的抽象,它封装了资源路径(我相信它是一个 SDK)。由于路径 (URL) 是从中抽象出来的,因此对于如何模拟此类库发出的请求,您至少有两种选择。
选项 1:使用显式路径
虽然隐藏了确切的资源路径,请求仍然引用现有的绝对路径。您可以在浏览器的“网络”选项卡中观察这些内容,或者通过使用 msw
:
// my.test.js
import { setupServer } from 'msw/node'
const server = setupServer(/* no handlers */)
beforeAll(() => server.listen())
afterAll(() => server.close())
Since we're using
setupServer
with no handlers, all requests that happen inmy.test.js
will be printed as warnings tostderr
. You can observe those warnings to see what resource paths your SDK requests.
使用 SDK 的好处是它可以保证您有一定的资源路径结构。最有可能的是,您将能够在模拟中复制该结构:
// src/mocks.js
import { rest } from 'msw'
export const handlers = [
rest.get('https://some-resource.:checksum.firebase.app/path', (req, res, ctx) => res(ctx.text('hello)))
]
Utilize dynamic path segments like
:checksum
to match a broader range of paths.
这种方法的缺点是您的模拟定义变得依赖于 SDK 内部细节(资源路径)。对 SDK 的任何更新都可能破坏您的模拟,因为它们可能会在内部更新路径结构而不将其表示为重大更改(抽象路径不是 public API)。
选项 2:监视 SDK
或者,您可以监视正在使用的 SDK。这种间谍的一个例子是直接在 react-query-firebase
上使用 jest.spyOn
:
// my.test.js
import * as reactQueryFirebase from 'react-query-firebase'
it('creates a user', () => {
jest.spyOn(reactQueryFirebase, 'SOME_METHOD_NAME')
.mockReturnValue(/* mock */)
})
此方法的缺点是您从第三方库中存根函数,这意味着您的测试代码永远不会调用这些函数。这会降低此类测试的可靠性,通常情况下,您应该避免采用这种方法。
我确实建议您研究 Firebase,因为主要的 SDK 提供商通常有关于模拟其 API 的指南。通常这样的指导会包括使用由 SDK 提供商编写的专用第三方包,允许模拟其内部资源。