使用 react-navigation 中的 useRoute 进行 Jest 单元测试

Posted

技术标签:

【中文标题】使用 react-navigation 中的 useRoute 进行 Jest 单元测试【英文标题】:Jest unit tests with useRoute from react-navigation 【发布时间】:2021-02-04 18:52:39 【问题描述】:

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

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

● <EULA /> › Rendering › should match to snapshot

    TypeError: Cannot read property 'name' of undefined

      27 |   const route = useRoute();
      28 |   const authContext = useContext(AuthContext);
    > 29 |   const isAcceptPP: boolean = route.name === "AcceptEULA";
         |                                     ^

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

这就是当前测试的样子,我尝试模拟 useRoute 并仅将 route 作为 props 的一部分,但这些似乎并没有起到什么作用:

import React from "react";
import  render, fireEvent, waitFor  from "@testing-library/react-native";
import  WebView  from "react-native-webview";
import  Alert  from "react-native";

import EULA from "../src/screens/EULA";
import  alertSpy  from "../src/jest/spies";

describe("<EULA />", () => 
  let props;
  let useRoute: jest.Mock;
  beforeEach(() => 
    useRoute = jest.fn();
    props =  navigation:  state:  routeName: "AcceptEULA" , navigate: navigate , route:  name: "AcceptEULA"  ;
  );

  describe("Rendering", () => 
    it("should match to snapshot when accept EULA", async () => 
      const  toJSON, getByType  = render(<EULA ...props />);
      await waitFor(() => getByType(WebView));
      expect(toJSON()).toMatchSnapshot();
    );

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

【问题讨论】:

如果没有一个最小的、完整的、可重现的代码,就无法提供帮助。 【参考方案1】:

我认为问题在于您将模拟路由作为prop 传递,而您的测试试图使用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 />);
    ...
  );
);

【讨论】:

以上是关于使用 react-navigation 中的 useRoute 进行 Jest 单元测试的主要内容,如果未能解决你的问题,请参考以下文章

react-navigation:从标题中的按钮导航到不同的屏幕

向@react-navigation/drawer 组件发送道具

如何使用 react-navigation 推送新场景?

React-navigation:与身份验证的深度链接

react-navigation:使用 Expo.addListener 在推送通知中导航的不变违规

react-navigation设置navigationOptions中Static中使用 this 的方法