正文
-
shallow()
-
mount()
-
render()
shallow() 只能用来渲染不包含 children 的组件,mount() 则能够渲染所有的子组件。所以单元测试的时候可以使用 shallow() ,mount() 则一般用于集成测试。集成测试往往是很容易被割裂的,因为他需要测试由一组或是多个组件树组合的场景,所以集成测试一般维护成本是比较高的。所以我们可以多做一些小巧的单元测试,少做一些重要的集成测试。
第三种测试的方式是使用 render() 方法,具有类似 mount()方法的功能,不过 mount() 能够访问到组件的生命周期方法,比如 componentDidUpdate等。
正如这个 issue 中提出的 API differences between render and mount/shallow,可以总结出:
-
使用 shallow 开始测试用例
-
如果 componentDidMount or componentDidUpdate 等方法也需要测试,那么使用 mount 方法吧
-
如果要测试组件生命周期方法、子组件的行为等,使用 mount 方法吧
-
如果想更高性能的测试子组件,并且对组件的生命周期等方法不怎么关注,那么使用 render 方法吧
保证测试用例简单、最小颗粒度
否则的话你需要为此付出很高的维护成本。
确认每个组件是否都有执行过单元测试,确认每个 props 和 callbacks 都在集成测试的时候传递给了对应的子组件。
为了保证组件测试用例的小颗粒度和简单化,你需要熟悉一下 selectors,Enzyme 提供了丰富的 selector 去深入组件树。
另外,建议使用 sinon 来测试 callbacks 回调函数,不要在组件中测试业务逻辑,这真不是个好注意。而是应该将业务逻辑从组件中解耦并对其进行测试。
最后,Facebook 出品的 Jest 也能在初期帮助我们更加轻量的执行测试,你可以非常简单就设置好 snapshot test,这样当组件的输出改变的话测试用例会自动的报出失败的结果,并且能够获取到错误信息。
拥抱 TDD(测试驱动开发)
所有的人都可能会对你说:你应该按测试驱动的模式来进行开发。但是,几乎没几个人会这么,项目需求如山的积压,上线的脚本火急火燎,测试驱动?玩呢?!可能大部分小伙伴都是这样的心声。
不过,如果你能够清晰的在 React + Redux 的应用中使用对应的测试方案对每个部分都进行测试,你就能够非常轻松的实现 TDD。尽管你会发现 reducer 的测试和组件的测试是很不一样的,但其实每种类型(reducer、component、…. )的测试模式其实都是一样的。
就拿 reducer 的测试为例吧,一般是期望 reducer(state, action) === newState,其实这种方式和 (input) => output 的模式是一样的。如果你要测试 state 的不可变性的话,建议你可以使用 deep-freeze,可以看下以下示例代码:
import deepFreeze
from
'deep-freeze'
const
initialState