React Native 是一种广泛使用的仿原生应用的跨平台开发框架,而 Enzyme 是一个流行的 React 测试库,常用于在 React Native 上测试组件。 但是,使用 Enzyme 测试 React Native 组件时,有时会遇到以下错误:
Cannot add a component `XXX` when a component `YYY` has already been added
这个错误信息通常表示同一测试中添加了相同的组件,但使用不同的名称。本文解释了这个错误的原因,并提供了解决方案以及可能的后续修补措施。
原因
问题的根源在于,Enzyme 本质上是通过更改 React 全局 React.Component.prototype
对象,来模拟组件树中的构造函数,并建立一个组件层次结构,其中所有的真实组件被替换为包装组件,Enzyme 为它们添加一组生命周期方法,用于跟踪组件的挂载、更新、卸载等过程。
这意味着,如果在同一个测试中,多次使用 mount()
或 shallow()
方法来构建相同的组件,并使用不同的变量名,Enzyme 将尝试重复添加该组件。
解决方案
为了解决此错误,我们需要强制 React 重新加载所有组件,以确保 Enzyme 对组件使用的类和其他属性在每次测试之间得到重置。我们可以通过以下步骤完成:
引入
react-test-renderer
:import renderer from 'react-test-renderer';
使用
create()
方法新建一个 React 渲染器实例,并使用createNativeComponent()
方法强制重新加载组件:const NewAppComponent = require('../path/to/App'); const Rerenderer = renderer.create( React.createElement(createNativeComponent(NewAppComponent), null));
在这个例子中,我们假定我们的组件名称是
App
,它位于相对路径../path/to/App
中,于是我们引入此文件并重新创建组件,通过createNativeComponent()
方法调用通知 React 强制重新加载组件。在测试之后,卸载并清除渲染器:
afterEach(() => { Rerenderer.unmount(); Rerenderer._root = null; });
后续修补措施
虽然上述解决方案很好,但如果您在复杂的测试套件中使用 Enzyme,您可能会遇到挑战:需要重复使用许多组件,而每次测试之间重新加载每个组件都会变得很麻烦。
解决此问题的一种方法是,引入一个将所有组件清除出 Enzyme 内部的列表("保护"列表)的功能,以防止重复添加相同的组件,如下所示。
-- -------------------- ---- ------- ----- ------------------------ - -- -- - ----- ----------------- - -------- -------- --- ------------ ----- ------------- - -------------------------- -------------------------- -- - -- ---------- -- ------ --------- --- ---------- -- ------------------- ---------- ---------------- - ----------- - ------ -- --------------------------------------------------- - ----------- - ----- - ---- -- ------------------------------------ -- -- - ----------- - ----- - -- ------------- - ------ ---------- - - --- -- ---------------------------
在这里,我们遍历 Enzyme 中所有的组件树节点,将查找 View
和 Text
这样被认为是 "保护" 的组件,如果有其他被保护的组件,可以在列表 protectedChildren
或纯 name
匹配上增加。在清除保护列表之后,我们可以使用 mount()
或 shallow()
方法安全地重复多次测试。
示例代码
-- -------------------- ---- ------- ------ ----- ---- -------- ------ - --------------------- - ---- --------------- ------ ------- - ----- - ---- --------- ------ ------- ---- -------------------------- ------ -------- ---- ---------------------- ------------------ -------- --- --------- --- ------------ ----- -- -- - --- ---------------- --- ----------- ----- --------------- - -------------------------- ----------------- -- - --------------- - --------------------------------- -------------------------------- - ------ ---------- - ---------------- ----------------------------------------------------------- ------- ------------------ ----------------------------------------------------------- ------- ---------------- ------ --- ------------ -- - --------------------- ---------------- - ----- --------------------------- --- ------ --- ------ -------- -- -- - ----- ------- - ------ ---------------- -- -- -------------------------------------- --- --- ----- ------------------------ - -- -- - ----- ----------------- - -------- -------- --- ------------ ----- ------------- - -------------------------- -------------------------- -- - -- ---------- -- ------ --------- --- ---------- -- ------------------- ---------- ---------------- - ----------- - ------ -- --------------------------------------------------- - ----------- - ----- - ---- -- ------------------------------------ -- -- - ----------- - ----- - -- ------------- - ------ ---------- - - --- -- ----- ---------------- - --------- -- - ----- ------------- - --- ----- ------------- - ------------------------------ ---------------------------------- ------------------------------- -- ---------------------------------------------------------- -- - ----------------------------------------------------------- ------------------- ------------------------------------------------------ -- --- ------ -------------- -- ----- ----------- - ------ -- - ----- -------- - --- -- ----- -- ----------------------- - ------------------------------------------------- -- - --------------------------------------------- ------------------------------------------------------------- --- - ------ --------- --
结论
Enzyme 是 React 测试的顶级选择之一,然而,在 React Native 中使用 Enzyme 测试组件时,会遇到“Cannot add a component XXX
when a component YYY
has already been added”这个小问题,而本文提供了解决方案和后续修补措施,以确保我们可以使用 Enzyme 安全和有效地测试 React Native 应用程序的组件。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/6716034fad1e889fe21a34aa