Jest 测试 React Native 应用程序

2021-09-18 20:41 更新

在 Facebook,我们使用 Jest 来测试React Native应用程序。

安装

从 react-native 0.38 版开始,运行​react-native init​. 以下配置应自动添加到 package.json 文件中:

  1. // package.json
  2. "scripts": {
  3. "test": "jest"
  4. },
  5. "jest": {
  6. "preset": "react-native"
  7. }

注意:如果你正在升级 react-native 应用程序并且之前使用了​jest-react-native​预设,请从​package.json​文件中删除依赖项并将预设更改为​react-native​。

用 yarn test 来运行 Jest 测试。

快照测试

下面来为一个入门的小型组件创建一个快照测试,它的内部有些View、Text组件和一些样式:

  1. // Intro.js
  2. import React, {Component} from 'react';
  3. import {StyleSheet, Text, View} from 'react-native';
  4. const styles = StyleSheet.create({
  5. container: {
  6. alignItems: 'center',
  7. backgroundColor: '#F5FCFF',
  8. flex: 1,
  9. justifyContent: 'center',
  10. },
  11. instructions: {
  12. color: '#333333',
  13. marginBottom: 5,
  14. textAlign: 'center',
  15. },
  16. welcome: {
  17. fontSize: 20,
  18. margin: 10,
  19. textAlign: 'center',
  20. },
  21. });
  22. export default class Intro extends Component {
  23. render() {
  24. return (
  25. <View style={styles.container}>
  26. <Text style={styles.welcome}>Welcome to React Native!</Text>
  27. <Text style={styles.instructions}>
  28. 这是一个 React Native 快照测试。
  29. </Text>
  30. </View>
  31. );
  32. }
  33. }

现在,使用React的test renderer和Jest的快照特性来和组件交互,获得渲染结果和生成快照文件:

  1. // __tests__/Intro-test.js
  2. import React from 'react';
  3. import renderer from 'react-test-renderer';
  4. import Intro from '../Intro';
  5. test('renders correctly', () => {
  6. const tree = renderer.create(<Intro />).toJSON();
  7. expect(tree).toMatchSnapshot();
  8. });

当你运行 ​npm test​ 或者 ​jest​,将产生一个像下面的文件:

  1. // __tests__/__snapshots__/Intro-test.js.snap
  2. exports[`Intro renders correctly 1`] = `
  3. <View
  4. style={
  5. Object {
  6. "alignItems": "center",
  7. "backgroundColor": "#F5FCFF",
  8. "flex": 1,
  9. "justifyContent": "center",
  10. }
  11. }>
  12. <Text
  13. style={
  14. Object {
  15. "fontSize": 20,
  16. "margin": 10,
  17. "textAlign": "center",
  18. }
  19. }>
  20. Welcome to React Native!
  21. </Text>
  22. <Text
  23. style={
  24. Object {
  25. "color": "#333333",
  26. "marginBottom": 5,
  27. "textAlign": "center",
  28. }
  29. }>
  30. This is a React Native snapshot test.
  31. </Text>
  32. </View>
  33. `;

下次你运行测试时,渲染的结果将会和之前创建的快照进行比较。快照应与代码更改一起提交。当快照测试失败,你需要去检查是否是你想要或不想要的变动。 如果变动符合预期,你可以通过​jest -u​调用Jest从而重写存在的快照。

示例代码可在 examples/enzyme 找到。

预设配置

预设设置了环境,并且非常的牢固,并且基于我们在 Facebook 发现的有用内容。所有配置选项都可以被覆盖,就像在不使用预设时可以自定义一样。

环境

react-native​附带一个 Jest 预设,因此​jest.preset​您的字段​package.json​应该指向​react-native​. 预设是一个模仿 React Native 应用程序环境的节点环境。因为它不加载任何 DOM 或浏览器 API,所以大大缩短了 Jest 的启动时间。

transformIgnorePatterns 自定义

transformIgnorePatterns选项可用于指定 Babel 应转换哪些文件。不幸的是,许多 react-native npm 模块在发布之前没有预编译它们的源代码。

默认情况下, jest-react-native 预设只处理项目自己的源文件和 react-native。如果有必须转换的 npm 依赖项,可以通过包含 react-native 以外的模块来自定义此配置选项:

  1. "transformIgnorePatterns": [
  2. "node_modules/(?!(react-native|my-project|react-native-button)/)"
  3. ]

设置文件

如果想为每个测试文件提供额外的配置,可以使用​setupFiles配置选项来指定安装脚本。

模块名称映射器

moduleNameMapper可用于一个模块路径映射到不同的模块。默认情况下,预设将所有图像映射到图像存根模块,但如果找不到模块,此配置选项可以提供帮助:

  1. "moduleNameMapper": {
  2. "my-module.js": "<rootDir>/path/to/my-module.js"
  3. }

提示

使用 jest.mock 模拟本机模块

内置的 Jest 预设​react-native​附带了一些应用于 react-native 存储库的默认模拟。但是,一些 react-native 组件或第三方组件依赖于本地代码来呈现。在这种情况下,Jest 的手动模拟系统可以帮助模拟底层实现。

例如,如果你的代码依赖于一个名为​react-native-video​的第三方本机视频组件,你可能希望使用这样的手动模拟将其存根:

  1. jest.mock('react-native-video', () => 'Video');

这将使组件呈现为​<Video{…props}/>​,其所有道具都将显示在快照输出中。想了解更多还可以阅读 caveats around Enzyme and React 16.

有时需要提供更复杂的手动模拟。例如,如果想将原生组件的 prop 类型或静态字段转发到模拟,可以通过 jest-react-native 的这个助手从模拟中返回不同的 React 组件:

  1. jest.mock('path/to/MyNativeComponent', () => {
  2. const mockComponent = require('react-native/jest/mockComponent');
  3. return mockComponent('path/to/MyNativeComponent');
  4. });

或者,如果想创建自己的手动模拟,可以执行以下操作:

  1. jest.mock('Text', () => {
  2. const RealComponent = jest.requireActual('Text');
  3. const React = require('React');
  4. class Text extends React.Component {
  5. render() {
  6. return React.createElement('Text', this.props, this.props.children);
  7. }
  8. }
  9. Text.propTypes = RealComponent.propTypes;
  10. return Text;
  11. });

在其他情况下,想要模拟不是 React 组件的本机模块。可以应用相同的技术。我们建议在真实设备上运行 React Native 应用程序时检查原生模块的源代码并记录模块,然后在真实模块之后对手动模拟进行建模。

如果你最终一遍又一遍地模拟相同的模块,建议在单独的文件中定义这些模拟并将其添加到​setupFiles​.


以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号