单元测试工具-Jest

1. 测试框架

框架
断言
异步
Mock
代码覆盖率

Jest

默认支持

友好

默认支持

支持

Mocha

不支持(Chai)

友好

不支持(Sinon)

不支持(Istanbul)

Ava

默认支持

友好

不支持(Sinon)

不支持(Istanbul)

2. Jest + Vue Test Utils

2.1 基础说明

如果使用的是 VUE CIL 的话,在创建项目时就选择 Jest 即可,或者后续添加配置即可,输入以下命令,会自动安装:

基本思路

  • Step1: 挂载组件 —— 通过 mount/shallowMount 方法来创建包裹器

  • Step2: 模拟必要的输入 (prop、注入和用户事件)

  • Step3: 对输出 (渲染结果、触发的自定义事件) 的断言来完成测试

测试描述

  • Given (如果) _ 指定的状态,通常是给出的条件(测试数据);

  • When (当) _ 触发一个动作或者事件;

  • Then (则) _ 对期望结果的验证;

举例:

  • it('Given a = 1 And b = 2,When execute add(),Then result is 3', () => {});

  • it('When 访问登录页面,Then 看到用户名、密码输入框和提交按钮', () => {})

2.2 Mock 依赖

Mock - 用于替代整个模块

jest.mock() 完全接管整个 ./sound-player JavaScript 模块,比如说这里的 playSoundFile 本来应该是从 ./sound-player 这个文件当中 export 出来的,而被 Mock 之后我们的测试就可以使用 Mock 所返回的数据或方法。注意,该模板的所有功能都已经被 Mock 掉,模块中其他功能也被mock了如果需要使用也需要重新实现。

Stub - 用于模拟特定行为

jest.fn() 代表着我就是一个 Stub(桩),可以是特定行为也可以是没有行为。没有行为常用于验证 Stub 被调用过,也就能够断言某处代码被执行,从而确定代码被测试所覆盖。特定行为就是返回特定的数据, Stub 也可以根据输入模拟返回一种输出。

Spy - 用于监听模块行为

Spy 并不会影响到原有模块的功能代码,而只是充当一个监护人的作用。比如说上文中的 video 模块中的 play() 方法已经被 spy 过,那么之后 play() 方法只要被调用过,我们就能判断其是否执行,甚至执行的次数。

2.3 异步测试

第一种:Vue 会异步的将未生效的 DOM 批量更新,避免因数据反复变化而导致不必要的渲染。因此在更新会引发 DOM 变化的属性后必须使用 Vue.nextTick() (异步函数)来等待 Vue 完成 DOM 更新。

第二种:在 Vuex 中进行 API 调用。

举例:按钮会处理一个异步函数

2.4 Vuex 测试

创建了一个 localVue 并对其安装 Vuex

2.5 路由测试

创建了一个 localVue 并对其安装 Vue Router

3. 踩坑指南

  • 注意,Vue 会异步的将未生效的 DOM 批量更新,避免因数据反复变化而导致不必要的渲染。因此在更新会引发 DOM 变化的属性后必须使用 Vue.nextTick() (异步函数)来等待 Vue 完成 DOM 更新。

  • 如果项目依赖第三方插件,建议将第三方插件注册到 localVue 中,mount 挂载组件生成 wrapper 时,将 localVue 作为参数传递。

  • elementUI 组件库与实际 html 不同,当一些事件无法触发(无法选中对应的 dom),可以打印 wrapper.html 看实际渲染结果。

  • 注意触发事件是在 dom 上通过 trigger() 触发,还是子组件触发事件通过 wrapper.vm.emit()。

  • 一个测试套件之间的测试用例肯能会互相影响,可使用钩子函数,在每次测试用例测试后都销毁。

如果你对内容有任何疑问,欢迎提交 ❕issues✉️ email

最后更新于

这有帮助吗?