前言
Enzyme 是 React 测试工具库中的重要成员,它具备了形如 jQuery 的 API,使得 React 组件的测试变得更加简单和可读性更高。但是,随着 React 不断更新迭代,Enzyme 也遇到了一些针对 React v16.4 的问题。
本篇文章主要介绍了通过一些基本的调整和技巧,解决 Enzyme 在 React v16.4 中出现的一些问题的方法。
##问题描述
React v16.4 以前的版本中,虚拟 DOM 的渲染是同步的,但是在 React v16.4 之后,渲染虚拟 DOM 变成了异步的。这使得 Enzyme 在渲染 React 组件时出现了一些问题。
具体来说,主要体现在 Enzyme 的渲染和断言过程中。
渲染问题
在 React v16.4 中,Enzyme 中的 shallow()
和 mount()
函数中,虚拟 DOM 渲染变成了异步的。
这意味着,在 Enzyme 中,与 React 的生命周期函数一起工作的模拟时机就会发生变化。在这种情况下,这些模拟需要等待 React 执行完生命周期方法,才能在 Enzyme 中进行更进一步的断言。
例如,我们以一个简单的 React Axios 应用为例:
-- -------------------- ---- ------- ------ ------ - --------- - ---- -------- ------ ----- ---- -------- ------ ----- -------- ------- --------- - ----------- ------- - ------------- ---------- - - ----- --- -------- ---- -- - ----------------- -- - --------------------------------------------------------- --------- -- - --------------- ----- --------- -------- ----- --- --- - ------ -- - ----- - -------- ---- - - ----------- ------ - ----- -------- - ------------ - --------------- -------------------- ----------------- ------------------------ ------ -- - -
我们可以使用 shallow()
把 AxiosGet 组件浅渲染一下,然后根据状态及加载情况来进行断言:
-- -------------------- ---- ------- ------ ----- ---- -------- ------ - ------- - ---- --------- ------ - -------- - ---- ------------- --------------- ---- ------- -- -- - ----------- ----- ------ -- -- - ----- ------- - ----------------- ---- ----------------------------------------------- ------------- -- - --------------------------------------- ------- ----------- --- ------ ------------- -- ------ --- ---
该测试不会通过,因为在 Enzyme 进行断言之前,由于虚拟 DOM 的异步渲染,Axios 请求还未完成,组件还在等待返回。
断言问题
在 React v16.4 中,Enzyme 中的 setState()
函数也变成了异步的。这意味着,在 setState()
之后进行的断言可能会出现一些问题,因为在最后更新之前,断言会在组件更新之前触发。
例如,我们以一个非常简单的 React 组件为例:
-- -------------------- ---- ------- ------ ------ - --------- - ---- -------- ----- ------- ------- --------- - ----------- ------- - ------------- ---------- - - ------ - -- - -------------- - -- -- - --------------- ------ ---------------- - - --- -- ------ -- - ----- - ----- - - ----------- ------ - ---- ------------------------------ --- ---------------------------------------------- ------- ---------------------------- ---------------------------------------- ------ -- - - ------ ------- --------
我们使用 mount()
将组件装载到虚拟 DOM 中,并对其进行交互和断言:
-- -------------------- ---- ------- ------ ----- ---- -------- ------ - ----- - ---- --------- ------ ------- ---- ------------ ----------------- ---- ------- -- -- - --- -------- ------------- -- - ------- - -------------- ---- --- ------------ -- - ------------------ --- ------------- ------ ------ ------- -------- -- -- - ----- ------- - ------------------------------------------------ ------------------------------- --- --------------- ------ ------ -------- --- --------- -- -- - ----- ------ - ----------------------------------------------- ----- ------- - ---------------------------------------------- ------------------------------------ ------------------------- ------------------------------------ --- ---
我们会发现,这个测试不会通过,因为启动检查和 Enzyme 状态更新之间的时间差异。当我们模拟点击增量按钮时,执行了 setState()
,而不是直接修改状态,所以断言错误地把旧状态与增量相加,而不是新状态。
解决方法
渲染问题
在工程项目中,我们可以尝试创建一个 async
函数。这个函数将会在传入了一个 React 组件的 Promise
上进行解析、解包和断言。将这个函数封装用到底层的 requestAnimationFrame
中,就可以使得每一次组件状态变化都能适当地等待。
-- -------------------- ---- ------- -- ------------ ------ ----- -------- --- --------- - ----- ------------------ ----------------- - ------ ----- -------- ------------------ --------- ------ - ----- ------------- -- ------- - -------- - -
现在我们可以使用这个 testAsyncComponent
函数来解决异步渲染测试的问题:
-- -------------------- ---- ------- ------ ----- ---- -------- ------ - ------- - ---- --------- ------ - -------- - ---- ------------- ------ - ------------------ - ---- -------------- --------------- ---- ------- -- -- - ----------- ----- ------ ----- -- -- - ----- ------- - ----- ----------------- ---- ----------------------------------------------- ----- ------------- --------------------------------------- ------- ----------- --- ------ ------------- --- ---
断言问题
在断言方案中,我们可以在组件 mount 后,通过组件实例对 setState()
进行修改。这将为 Enzyme 和 React 生命周期函数提供相同的上下文,使得它们同步化,从而解决了我们遇到的问题。
-- -------------------- ---- ------- ------ ----- ---- -------- ------ - ----- - ---- --------- ------ ------- ---- ------------ ----------------- ---- ------- -- -- - --- -------- ------------- -- - ------- - -------------- ---- --- ------------ -- - ------------------ --- ------------- ------ ------ ------- -------- -- -- - ----- ------- - ------------------------------------------------ ------------------------------- --- --------------- ------ ------ -------- --- --------- -- -- - ----- ------ - ----------------------------------------------- --------------------------------------- ------------------------- --------------------------------------- --- ---
在这个示例中,我们使用了 mount(),因为它与 React 生命周期进行更紧密的集成。
结论
通过尝试针对 Enzyme 和 React v16.4 的不同工作方式进行微调或使用特殊技巧,可以解决许多 Enzyme 在渲染和断言时出现的问题。
使用 async
和 Enzyme 的 update()
函数结合使用,我们可以解决 Enzyme 中异步渲染的测试问题。同时,在断言状态更新方面,可以尝试直接修改实例的 state 状态,避免 Enzyme 状态更新之间的时间差异。
这些方法对 Enzyme 或 React 的工作方式不是理解,而是一个真正的经验问题。使用上述方法可以帮助开发者在 Enzyme 和 React v16.4 的情况下高效地构建和测试组件。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67186a8ead1e889fe22ae99a