如何测试基于 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 提供商编写的专用第三方包,允许模拟其内部资源。