【问题标题】:How to test React Native component with NavigationEvents in jest如何用 NavigationEvents 开玩笑地测试 React Native 组件
【发布时间】:2020-03-08 11:25:44
【问题描述】:

如何为包含 NavigationEvents 子组件的 react 本机组件编写一个有趣的单元测试。

我已经尝试了问题herehere 中提供的解决方案,但没有成功。

我得到的错误是

    console.error node_modules/react-test-renderer/cjs/react-test-renderer.development.js:9215
      The above error occurred in the <Context.Consumer> component:
          in withNavigation(NavigationEvents) (created by MyComponent)
          in View (created by View)
          in View (created by MyComponent)
          in MyComponent

      Consider adding an error boundary to your tree to customize error handling behavior.

  ● MyComponent test › renders

    Invariant Violation: withNavigation can only be used on a view hierarchy of a navigator. The wrapped component is unable to get access to navigation from props or context.

以下是导致错误的最小示例。

import 'react-native';
import { View } from 'react-native';
import { NavigationEvents } from 'react-navigation';
import React from 'react';
import renderer from 'react-test-renderer';

class MyComponent extends React.Component {

    constructor(props) {
      super(props);
    }

    render() {
        return (
          <View>
            <NavigationEvents/>
          </View>
        );}
  }

describe('MyComponent test', () => {
    it('renders', () => {

        jest.mock('react-navigation', () =>({
            NavigationEvents: 'mockNavigationEvents',
            withNavigation: component => component
          }));
        const navigation = { navigate: jest.fn() };

        renderer.create(<MyComponent navigation={navigation}/>);
    });
});

编辑

根据 cmets 的要求在下方添加 package.json


{
  "main": "node_modules/expo/AppEntry.js",
  "scripts": {
    "start": "expo start",
    "android": "expo start --android",
    "ios": "expo start --ios",
    "eject": "expo eject",
    "test": "node ./node_modules/jest/bin/jest.js --watchAll"
  },
  "jest": {
    "preset": "jest-expo"
  },
  "dependencies": {
    "@expo/samples": "2.1.1",
    "@expo/vector-icons": "^10.0.0",
    "expo": "^35.0.0",
    "expo-camera": "~7.0.0",
    "expo-sqlite": "^7.0.0",
    "moment": "^2.24.0",
    "react": "16.8.3",
    "react-native": "https://github.com/expo/react-native/archive/sdk-35.0.0.tar.gz",
    "react-native-action-button": "^2.8.5",
    "react-native-calendar-picker": "^6.0.0",
    "react-native-dialog": "^5.6.0",
    "react-native-dotenv": "^0.2.0",
    "react-native-dynamic-search-bar": "^0.1.11",
    "react-native-elements": "^1.1.0",
    "react-native-gesture-handler": "~1.3.0",
    "react-native-keyboard-aware-scroll-view": "^0.9.1",
    "react-native-modal-datetime-picker": "^7.4.0",
    "react-native-paper": "^2.15.2",
    "react-native-progress-circle": "^2.1.0",
    "react-native-search-bar": "^3.4.2",
    "react-native-vector-icons": "^6.4.2",
    "react-navigation": "^3.0.9",
    "expo-constants": "~7.0.0",
    "expo-file-system": "~7.0.0"
  },
  "devDependencies": {
    "babel-preset-expo": "^7.0.0",
    "jest-expo": "^35.0.0"
  },
  "private": true
}

expo-cli 版本

$ expo-cli -V
3.13.1

【问题讨论】:

  • 您可能在package.json 中有一些jest 配置与模拟react-navigation 函数冲突。您能分享您的package.json 内容吗?我已经使用RN 0.61react-navigation@4.2.2 测试了您的代码,它通过了测试,没有任何错误。
  • @ChristosLytras 有趣...我添加了package.json
  • 您正在使用您在任何地方都没有提及的 Expo,这是一个非常重要的信息。 Expo 的行为与正常的 RN 项目不同。请分享您正在使用的 Expo CLI 和版本。 编辑我可以在package.json看到版本,我会检查一下。

标签: reactjs react-native unit-testing jestjs


【解决方案1】:

问题是jest.mock 必须在describeit 函数之外。您无需手动模拟 navigation 对象,因为您正在模拟 withNavigation HOC 函数:

// Setup mocks outside describe and it functions
jest.mock('react-navigation', () =>({
  NavigationEvents: 'mockNavigationEvents',
  withNavigation: component => component
}));

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
  }

  render() {
    return (
      <View>
        <NavigationEvents/>
      </View>
    );
  }
}

describe('MyComponent test', () => {
  it('renders', () => {
    renderer.create(<MyComponent/>);
  });
});

renders 测试通过:

我建议你将所有这些模拟放在一个文件中,并将setupFilesAfterEnv 设置为package.json

package.json > jest:

"jest": {
  "preset": "jest-expo"
  "setupFilesAfterEnv": ["./path/to/jestInit.js"]
},

jestInit.js:

jest.mock('react-navigation', () =>({
  NavigationEvents: 'mockNavigationEvents',
  withNavigation: component => component
}));

这样,您将拥有每个 Jest 测试文件的这些模拟,而不必在每个测试文件中包含模拟。

【讨论】:

  • 啊!很简单。非常感谢。有没有一个快速的答案,为什么它必须在 describe 之外?
  • 不客气。它必须在 describe 之外,因为此时 Jest 已经加载了导入的文件,所以它不能覆盖任何东西。
  • I0m 遇到此配置的另一个问题:TypeError: Cannot read property 'light' of undefined
猜你喜欢
  • 2020-04-20
  • 2021-06-28
  • 1970-01-01
  • 2021-08-01
  • 2017-08-25
  • 2017-07-13
  • 1970-01-01
  • 2021-01-09
  • 2019-11-22
相关资源
最近更新 更多