用 Jest 单元测试基于 Vue 的项目

- hikerpig
#Test#Vue

为一个基于 Vue 的项目搭建测试框架,有两个比较成熟的选择,Mocha + Webpack + Karma,或是 Jest。

前者也是 vue-cli 默认脚手架里的测试方案,我们之前的项目也用了它,实际使用起来,感觉成也 Karma,败也 Karma,配置起来不是很顺手,导致测试必须在完整打包后才能进行,测试时间随着用例增加飞速增长。而且调试单个测试用例的时候冷启动时间太长。

最后采用了功能强大的 Jest。

写测试

测试 Vue 组件

参见 Vue Cookbook 中关于单元测试的一章,以及 vue test-utils 的文档

拦截网络请求

由于目前请求都通过 axios,可以简单地通过对 axios 对象的劫持来实现这一需求,考虑 axios-mock-adapter 插件。

拦截定时器

看Jest 文档的 Timer Mocks 一章。

自定义 Mock

采用 Jest 一方面是因为它具有很方便的 Mock 方案,框架会自动探测 __mocks__ 文件夹中的文件,例如如果新建 __mocks__/axios.js,测试中所有源码的 require('axios') 返回的对象都会是该文件的导出内容。详见文档中的 Manual Mocks 一章。

调试测试

以在 VSCode 中 Debug 的配置为例,以下为 .vscode/launch.json 示例,参考文章《在VS Code中调试Jest单元测试》

{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "Debug Current Jest Test",
      "program": "${workspaceRoot}/node_modules/jest/bin/jest",
      "cwd": "${workspaceRoot}",
      "env": {
        "NODE_ENV": "test"
      },
      "args": ["--runInBand", "--env=jsdom", "${fileBasename}"],
      "runtimeArgs": [
        "--inspect-brk",
      ],
      "sourceMaps": true,
      "console": "integratedTerminal",
      "internalConsoleOptions": "neverOpen",
    },
    {
      "type": "node",
      "request": "attach",
      "stopOnEntry": false,
      "name": "Attach to node inspect-brk",
      "port": 9229
    },
  ]
}

使用 VSCode 启动测试

args 中的 --runInBand--env=jsdom 都是 Jest 的配置项,详细的可查阅 jest cli 文档

${fileBasename} 为 VSCode 配置提供的变量,在此处表明只让 Jest 运行当前打开文件描述的用例。

通过调试协议连接进程

可以不通过 VSCode,而是直接使用命令 node --inspect=9229 --inspect-brk ./node_modules/.bin/jest --runInBand 运行 jest,

第二个配置(request 为 'attach'),连接一个开放 9229 为调试端口的已经在运行的 node 进程。

此种方式可选择其他实现了远程调试协议的IDE(例如 Webstorm)或浏览器(例如 chrome://inspect )来实现断点调试等功能。

关于 Inspector 协议可看此文章