专栏名称: xiaoT
前端开发
目录
相关文章推荐
每天发现一家店  ·  今天这 12 件情人节礼物,好美! ·  2 天前  
武汉本地宝  ·  武汉元宵节8个亲子好去处推荐! ·  昨天  
武汉本地宝  ·  家长快看!武汉五区幼儿园入园体检指南来啦! ·  2 天前  
武汉本地宝  ·  武汉本周消费券领取时间一览表 ·  2 天前  
武汉本地宝  ·  武汉公积金账户的钱可以全额提取吗? ·  3 天前  
51好读  ›  专栏  ›  xiaoT

用 Jest 和 Enzyme 测试 React I

xiaoT  · 掘金  ·  · 2020-04-21 02:56

正文

阅读 17

用 Jest 和 Enzyme 测试 React I

原文地址: medium.com/codeclan/te…
译文地址: github.com/xiao-T/note…
本文版权归原作者所有,翻译仅用于学习。


这篇文章将会介绍如何设置并使用 Jest Enzyme 测试通过 Create React App (CRA) 创建的 React 应用。对于那些从头开始的人我们会给出一些建议。但是,不会涉及太多有关 React 的知识。

Jest 和 Enzyme 是两个不同,但又相互相成的工具,整合在一起可以提供更加灵活和更具创造性的测试能力。我们将会简单介绍两者有什么差异。

Jest

Jest 是一个 Javascript 单元测试框架,Facebook 用来测试服务和 React 应用。

CRA 已经内置了 Jest;不再需要单独安装。

Jest 是一个 测试运行器 断言库 模拟库

Jest 也提供 快照 测试,它可以创建一个组件的快照,然后与上一次保存快照对比。如果,前后两者不匹配,测试就会失败。快照将会被保存在名为 __snapshots__ 文件夹中,它与被测试的文件在同一目录中。快照看起来就像下面这个样子:

exports[`List shallow renders correctly with no props 1`] = `
<List
  ordered={false}
>
  <ListItem>
    Item 1
  </ListItem>
  <ListItem>
    Item 1
  </ListItem>
</List>
`;
复制代码

快照测试必须结合浏览器测试,并且,在一开始就要校验快照,以保证快照能按照期望的输出。

Enzyme

Enzyme 是针对 React 的测试功能库,它可以更容易的断言、操控和遍历 React 组件。

Enzyme,由 Airbnb 创建,并添加了更好的功能方法,比如: 渲染组件 查找元素 与元素交互

在 CRA 中它必须单独安装。

Jest 和 Enzyme

  • Jest 和 Enzyme 两者都可以测试 React 应用,Jest 还可以测试其他的 Javascript 应用,但是 Enzyme 只能测试 React。
  • Jest 可以单独渲染组件和快照测试,Enzyme 只是添加了更简单的方法。
  • 没有 Jest,Enzyme 也可以使用,但是 必须 结合另外的测试运行器(runner)。

综上所述:

  • Jest 作为测试运行器,断言库和模拟器使用
  • Enzyme 提供额外的测试功能用与交互。

设置

安装和配置

如果不使用 CRA,需要安装 Jest:

npm install --save-dev jest babel-jest
复制代码

安装 Enzyme:

npm install --save-dev enzyme enzyme-adapter-react-16 enzyme-to-json
复制代码

更新 package.json

"jest": {
  "snapshotSerializers": ["enzyme-to-json/serializer"]
}
复制代码

相比 Enzyme,为了更加方便的对比快照, enzyme-to-json 提供了更好组件格式化方式。当使用快照时 snapshotSerializers 可以更大限度的压缩重复代码。如果没有指定序列化工具,测试中每次对比快照是否匹配时都需要把组件传递给 enzyme-to-json .toJson() 方法,反之,就不需要。

expect(toJson(rawRenderedComponent)).toMatchSnapshot();
复制代码

通过在 package.json 中添加这一配置,在你调用 Jest 的 .toMatchSnapshot() 时就不需要在调用 JSON 格式化方法了。

./src/setupTests.js 创建 setupTets.js 文件:

import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';configure({ adapter: new Adapter() });
复制代码

CRA 会自动搜索这个文件,如果,你没有使用 CRA,这时你就需要在 snapshotSerializers 的相同位置添加这一配置:

"setupFiles": ["./src/setupTests.js"],
复制代码

创建测试文件

Jest 将会在符合以下规则的地方 查找所有的测试文件

  • 文件夹 __tests__ 中以 .js 结尾的文件
  • .test.js 结尾的文件
  • .spec.js 结尾的文件

比较方便的是把每个测试文件和需要测试代码放在同一目录下。这在语义上更加有意义,同时也会让相对路径更加简单( ./MyComponent vs ../../MyComponent )。

以下是 MyComponent.test.js 的演示:

import React from 'react';
import { shallow } from 'enzyme';
import MyComponent from './MyComponent';

describe('MyComponent', () => {
  it('should render correctly in "debug" mode', () => {    const component = shallow(<MyComponent debug />);
  
    expect(component).toMatchSnapshot();
  });
});
复制代码

在 CRA 环境下,当执行 npm test 时会运行所有的测试文件并把结果输出到终端。通过自定义标签 -- --testPathPattern filename/ 可以指定只运行特定的文件或者使用 -- --testPathIgnorePatterns filename/ 来忽略指定的文件。

Mount, Shallow, Render

import { mount, shallow, render } from ‘enzyme';
复制代码

为了测试组件以上的方法肯定会用到,就如上一段代码所示。

Mounting

  • 完整的 DOM 渲染,包括子组件
  • 对于需要和 DOM 交互、完整测试组件生命周期情况,这是最理想渲染方式
  • 因为是真实把组件渲染成 DOM,为了不影响其他的测试,每次测试完成都需要调用 .unmount()
  • 允许直接访问传递给 root 组件(包括默认的)和传递给子组件的 props。

Shallow

  • 只渲染单个组件,不包括子组件。这对于需要隔离组件做单纯的单元测试非常有用。它可以防止因为子组件的改变和 bugs 影响组件测试的结果。
  • 在 Enzyme 3 中 shallow 渲染默认也可以访问组件的生命周期方法。
  • 不能访问传递给 root 组件的 props(因为它们不是默认 props),但是,它们可以传递给子组件,也可以测试传递的 props 是否对组件有 影响 。也就说 shallow 可以测试组件的渲染,但不能测试其中的 element。

Render

  • 把组件渲染成静态的 HTML,包括子组件
  • 不能访问 React 的生命周期方法
  • 相比 mount 成本更低,但功能也更少

Testing

基本的组件渲染

一个简单无交互的组件:

it('should render correctly with no props', () => {
  const component = shallow(<MyComponent/>);
  
  expect(component).toMatchSnapshot();
});
it('should render banner text correctly with given strings', () => {
  const strings = ['one', 'two'];
  const component = shallow(<MyComponent list={strings} />);
  expect(component).toMatchSnapshot();
});
复制代码

事件

Enzyme API 有好几种方式可以模拟事件或者用户交互。如果,你想测试子组件的交互功能,这时就需要 mount 方法了。

it('should be possible to activate button with Spacebar', () => {
  const component = mount(<MyComponent />);
  component
    .find('button#my-button-one')
    .simulate('keydown', { keyCode: 32 });
  expect(component).toMatchSnapshot();
  component.unmount();
});
复制代码

模拟方法

或许你只是想简单验证下通过 prop 传递的方法是否成功执行。

const clickFn = jest.fn();
describe('MyComponent', () => {
  it('button click should hide component', () => {
    const component = shallow(<MyComponent






请到「今天看啥」查看全文


推荐文章
每天发现一家店  ·  今天这 12 件情人节礼物,好美!
2 天前
武汉本地宝  ·  武汉元宵节8个亲子好去处推荐!
昨天
武汉本地宝  ·  武汉本周消费券领取时间一览表
2 天前
武汉本地宝  ·  武汉公积金账户的钱可以全额提取吗?
3 天前
读书小分队  ·  改变男人,只有一个办法
7 年前
FXWS  ·  接受亏损(接受不完美)
7 年前
笑的合不拢嘴  ·  农村媳妇考驾照,教练太坏!
7 年前