EnzymeJS 从 v2 迁移到 v3 的完整指南

EnzymeJS 从 v2 迁移到 v3 的完整指南

enzyme JavaScript Testing utilities for React enzyme 项目地址: https://gitcode.com/gh_mirrors/en/enzyme

前言

EnzymeJS 是一个广受欢迎的 React 测试工具库,它提供了简洁的 API 来测试 React 组件的输出和行为。从 v2 升级到 v3 是一个重大的版本变更,因为内部实现几乎完全重写。本文将详细介绍迁移过程中需要注意的关键变化和最佳实践。

核心架构变化

Enzyme v3 引入了全新的适配器(Adapter)系统,这是与 v2 最大的不同之处。这个变化带来了几个重要优势:

  1. 减少对 React 内部实现的依赖
  2. 支持更多类 React 库(如 Preact 和 Inferno)
  3. 更稳定和可预测的测试行为

适配器配置

在 v3 中,你必须显式配置适配器才能使用 Enzyme。这是与 v2 最大的使用差异。

安装适配器

首先需要安装对应 React 版本的适配器包:

npm install enzyme-adapter-react-16 --save-dev

配置示例

import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';

// 在测试文件顶部配置适配器
Enzyme.configure({ adapter: new Adapter() });

适配器版本对应表

| 适配器包名 | 兼容的 React 版本 | |------------|------------------| | enzyme-adapter-react-16 | ^16.4.0-0 | | enzyme-adapter-react-16.3 | ~16.3.0-0 | | enzyme-adapter-react-15 | ^15.5.0 | | enzyme-adapter-react-14 | ^0.14.0 | | enzyme-adapter-react-13 | ^0.13.0 |

主要破坏性变更

1. 元素引用标识不再保留

在 v2 中,Enzyme 会保留 React 元素的原始引用。v3 中由于中间表示层的引入,这种引用关系不再保持。

示例代码

const ICONS = {
  success: <Icon name="check-mark" />,
  failure: <Icon name="exclamation-mark" />,
};

function StatusLabel({ id, label }) {
  return <div>{ICONS[id]}{label}{ICONS[id]}</div>;
}

测试差异

  • v2: wrapper.find(Icon).length 返回 1
  • v3: 返回 2

虽然这是一个破坏性变更,但新行为更符合用户预期,测试结果也更加稳定。

2. 状态更新后需要手动更新包装器

在 v2 中,组件状态变化会自动反映在包装器中。v3 中需要显式调用 update() 方法。

最佳实践

const wrapper = shallow(<Counter />);
wrapper.instance().increment();
wrapper.update(); // 必须手动调用
expect(wrapper.find('.count').text()).toEqual('1');

3. children() 方法行为变化

children() 现在返回渲染后的子元素,而不是 props.children。

示例

class Box extends React.Component {
  render() {
    return <div className="box">{this.props.children}</div>;
  }
}

const wrapper = mount(<Box><div className="child" /></Box>);
  • v2: wrapper.children() 返回 <div className="child" />
  • v3: 返回 <div className="box"><div className="child" /></div>

4. find() 方法返回主机节点和DOM节点

.find() 现在会同时返回主机节点和DOM节点。如果需要只查找DOM节点,可以使用更具体的查询:

wrapper.find('div.bar') // 只查找DOM节点

5. ref() 方法行为变化

ref() 现在返回实际的 ref 引用,而不是包装器。

v2 vs v3

class Box extends React.Component {
  render() {
    return <div ref="abc">Hello</div>;
  }
}

const wrapper = mount(<Box />);
// v2: wrapper.ref('abc') 返回包装器
// v3: 返回实际的 DOM 元素

如果需要获取包装器,可以使用:

wrapper.findWhere(n => n.instance() === wrapper.ref('abc'))

其他重要变更

1. 实例访问

现在可以在树的任何层级调用 .instance()

const wrapper = mount(<Parent><Child /></Parent>);
const childInstance = wrapper.find(Child).instance();

2. getNode() 方法替换

  • 对于 mount: 使用 .instance() 替代 .getNode()
  • 对于 shallow: 使用 .getElement() 替代 .getNode()

3. 私有属性移除

以下私有属性已被移除:

  • .node
  • .nodes
  • .renderer
  • .unrendered
  • .root
  • .options

4. Cheerio 升级

render() API 使用的 Cheerio 已升级到 1.0.0,行为可能有变化。

迁移建议

  1. 逐步迁移:先在一个小型项目或测试文件中尝试迁移
  2. 关注测试覆盖率:确保关键功能有良好的测试覆盖
  3. 利用类型检查:TypeScript 或 Flow 可以帮助发现 API 变更
  4. 团队沟通:确保所有开发人员了解变更

常见问题解决方案

问题1:测试突然失败

解决方案

  • 检查是否配置了正确的适配器
  • 确认是否需要在状态更新后调用 update()
  • 验证 find() 查询是否过于宽泛

问题2:ref 相关测试失败

解决方案

  • 修改测试以直接使用 ref 对象
  • 或者使用 findWhere 获取包装器

问题3:children 断言失败

解决方案

  • 更新断言以匹配新的 children() 行为
  • 考虑使用 props() 获取原始 children

结论

Enzyme v3 的架构改进为长期稳定性和扩展性奠定了基础。虽然迁移需要一些工作,但 Airbnb 的经验表明,99.6% 的测试无需修改就能通过。对于必须修改的测试,这些变更通常会使测试更加健壮和符合预期。

通过理解这些关键变更点,你可以更顺利地完成从 v2 到 v3 的迁移,并享受新版本带来的各种优势。

enzyme JavaScript Testing utilities for React enzyme 项目地址: https://gitcode.com/gh_mirrors/en/enzyme

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雷芯琴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值