使用反应导航中的 useRoute 进行 Jest 单元测试

use*_*842 6 unit-testing jestjs react-native react-navigation react-hooks

我们最近将 React Native 代码库升级到了 React Navigation 的第 5 版,并且在此过程中我们将一些组件从类组件重构为功能组件。这意味着我们正在使用像 useNavigation() 和 useRoute() 这样的钩子。

\n

我很难弄清楚如何解决我们在进行单元测试时遇到的问题。看起来导航和路线道具的状态在运行时不可用于测试。例如,我从 Jest 收到以下错误:

\n
\xe2\x97\x8f <EULA /> \xe2\x80\xba Rendering \xe2\x80\xba should match to snapshot\n\n    TypeError: Cannot read property 'name' of undefined\n\n      27 |   const route = useRoute();\n      28 |   const authContext = useContext(AuthContext);\n    > 29 |   const isAcceptPP: boolean = route.name === "AcceptEULA";\n         |                                     ^\n
Run Code Online (Sandbox Code Playgroud)\n

这个错误让我相信,当第 27 行在单元测试的上下文中运行时,它实际上并没有从 useRoute() 返回路由对象。此错误出现在我对该文件的所有测试中。

\n

这就是当前测试的样子,我尝试模拟 useRoute 并将路由作为 props 的一部分,但这些似乎没有做任何事情:

\n
import React from "react";\nimport { render, fireEvent, waitFor } from "@testing-library/react-native";\nimport { WebView } from "react-native-webview";\nimport { Alert } from "react-native";\n\nimport EULA from "../src/screens/EULA";\nimport { alertSpy } from "../src/jest/spies";\n\ndescribe("<EULA />", () => {\n  let props;\n  let useRoute: jest.Mock;\n  beforeEach(() => {\n    useRoute = jest.fn();\n    props = { navigation: { state: { routeName: "AcceptEULA" }, navigate: navigate }, route: { name: "AcceptEULA" } };\n  });\n\n  describe("Rendering", () => {\n    it("should match to snapshot when accept EULA", async () => {\n      const { toJSON, getByType } = render(<EULA {...props} />);\n      await waitFor(() => getByType(WebView));\n      expect(toJSON()).toMatchSnapshot();\n    });\n
Run Code Online (Sandbox Code Playgroud)\n

我对 Jest 还是有点陌生​​,我不太确定我应该如何处理这个问题,因为路线不再是导航道具的一部分,但我可能只是想得太多了。

\n

小智 8

我认为问题在于您将模拟路由作为 a 传递prop,而您的测试试图使用 a 捕获路由hook

我认为这可以帮助你:

import { useRoute } from "@react-navigation/core";
jest.mock("@react-navigation/core");
import EULA from "../src/screens/EULA";

describe("Rendering", () => {
  it("should match to snapshot when accept EULA", async () => {
    useRoute.mockReturnValue({
      name: "AcceptEULA"
    });
    const { toJSON, getByType } = render(<EULA />);
    ...
  });
});
Run Code Online (Sandbox Code Playgroud)