关于组件测试 Vue 有官方的组件测试库Vue Test Utils ,这是一个比较偏底层的组件测试库, 如果对其不熟悉的话,官方建议是使用Vue Testing Library , 它是对 Vue Test Utils 的抽象
项目添加组件测试
使用 vite 创建 Vue 应用
1 yarn create vite <project_name> --template vue
安装依赖
testing library 目前只针对 Vue2 进行了适配,如果需要在 Vue3 中使用,需要安装 6.x.x 版本
在使用 testing library 处理组件,它会返回一些选择器,让你根据不同的方式获取组件中的 DOM 元素, 所以在用 testing library 测试的时候,可能会需要确认某个 DOM 是否被正确的渲染出来,但 jest 本身 并没有提供这些断言的方法,所以才需要jest-dom 来扩充对 DOM 的断言方式
1 yarn add jest @testing-library/vue@next babel-jest @babel/core @babel/preset-env -D
babel 配置
1 2 3 4 5 6 7 8 9 10 11 12 module .exports = { presets : [ [ '@babel/preset-env' , { targets : { node : 'current' } } ] ] };
jest 配置
transform 配置中添加了针对不同文件的转换规则,如果需要测试的文件 不是 Vue3 和 js 则需要安装对应的插件并修改 transform 配置,例如如果使用 Vue2 的话可以安装@vue/vue2-jest,使用 ts 话则可以安装 ts-jest
1 2 3 4 5 6 7 8 9 10 module .exports = { testEnvironment : 'jsdom' , transform : { '^.+\\.vue$' : '@vue/vue3-jest' , '^.+\\js$' : 'babel-jest' }, testRegex : '(/__tests__/.*|(\\.|/)(test|spec))\\.js$' , moduleFileExtensions : ['vue' , 'js' ], transformIgnorePatterns : ['/node_modules/(?!testing-library)' ] };
修改 package.json,添加测试命令
1 2 3 "scripts" : { "test" : "jest" } ,
简单的测试 1 2 3 4 5 6 7 8 9 10 11 12 13 import '@testing-library/jest-dom' ;import { render } from '@testing-library/vue' ;import HelloWorld from './HelloWorld.vue' ;describe ('HelloWorld.vue' , () => { it ('renders props.msg when passed' , () => { const msg = 'new message' ; const { getByText } = render (HelloWorld , { props : { msg } }); expect (getByText (msg)).toBeInTheDocument (); }); });
在需要测试的组件的同级目录下创建同名测试文件,例如上述针对 HelloWorld 的组件需要创建 HelloWorld.spec.js 文件
在测试文件中引入 jest-dom 来扩充 jest 的断言方法
上面的测试用例是用来测试组件是否正确地渲染,所以需要从 DOM 中获取渲染的内容,render 方法用来渲染组件,而 getByText 会试着去获取内容为 msg 的 DOM,并交给 jest 的 expect 方式,最后用 jest-dom 扩充的 toBeInTheDocument 去验证,看 getByText 有没有 找到 DOM,如果有的话就代表 HelloWorld 通过了测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import '@testing-library/jest-dom' ;import { render, fireEvent } from '@testing-library/vue' ;import Counter from './Counter.vue' ;describe ('increments value on click' , () => { it ('click twice' , async () => { const { getByText } = render (Counter ); getByText ('Times clicked: 0' ); const button = getByText ('increment' ); await fireEvent.click (button); await fireEvent.click (button); expect (getByText ('Times clicked: 2' )).toBeInTheDocument (); }); });
有时,我们也想看一下带有交互事件的组件是否能正常工作,这个时候就需要用到 fireEvent 函数了. fireEvent 用来模拟用户交互行为.在上面 Counter 测试中,用户点击两次后查看 DOM 中是否有含有 特定字符串的节点.