前言
前一段时间公司让前端写单元测试,于是乎就研究了下JEST。从安装到落地一路坎坷呀,因为淋雨过所以想为人撑伞,把自己遇到的问题和搜集到的都分享出来,欢迎大家补充内容。(技术是没边界的,即使我在公司内部也分享过,仍不影响继续分享给大家)
一、安装包并运行命令后报错类问题
1、未安装测试运行器运行环境jest-environment-jsdom
window is undefined, vue-test-utils needs to be run in a browser environment.You can run the tests in node using jsdom
早期的jest会默认安装JSDOM的运行环境,但是在28版本后,已取消默认安装,需要自己手动安装jest-environment-jsdom,执行jest运行环境。
npm install --save-dev jest-environment-jsdom
在package.json中加入
// package.json
{
// ...
"jest": {
// ...
"testEnvironment": "jsdom"
}
}
2、安装jest-babel报错
2.1 提示:Error: Cannot find module ‘babel-core’
查找issue后发现,主要是因为babel-loader和babel-core版本不匹配导致的。
babel-loader v8.x 应该对应 babel-core v7.x
babel-loader v7.x 应该对应 babel-core v6.x
所以需降低babel-core版本:
npm install --save-dev babel-core@^7.0.0-bridge.0
2.2 提示:Requires Babel “^7.0.0-0”, but was loaded with “6.26.3”.
描述:
安装jest-babel
后,提示让安装babel-core
,执行npm install --save-dev babel-core
安装后版本不匹配报错。
解决:
安装指定版本 “babel-core”: “^7.0.0-bridge.0”
npm uninstall jest babel-jest babel-core @babel/core
npm install --save-dev jest babel-jest babel-core@^7.0.0-bridge.0 @babel/core
3、提示:ReferenceError: Vue is not defined
查找 issue 后发现,其原因主要是 jest-environment-jsdom 和@vue/test-utils配置冲突导致的。引入 jest-environment-jsdom时,jest会自动设置特定的导入方式,再引入@vue/test-utils时设置了customExportConditions配置项,导致Jest 最后使用了CommonJS的导入方式,修改如下:
// package.json
{
// ...
"jest": {
// ...
"testEnvironmentOptions": {
"customExportConditions": ["node", "node-addons"]
},
}
}
4、提示:TypeError: Cannot destructure property ‘createComponentInstance’ of ‘Vue.ssrUtils’ as it is undefined
此问题是由于@vue/test-utils与vue版本不匹配导致的,按照官网的描述:
@vue/test-utils v2.x 应该对应 vue v3.x
@vue/test-utils v1.x 应该对应 vue v2.x
需对@vue/test-utils进行降级处理:
npm install --save @vue/test-utils@v1.3.5
二、测试用例编写过程遇到的坑点
1、在测试组件中使用了第三方组件或其他基础组件,如Element UI等
报错场景包括:
- 测试组件使用了全局定义的第三方组件
Vue.use(ElementUI, { locale, size: 'small' })
- 测试组件按需引入第三方组件
import { Input } from 'element-ui'
- 自定义基础组件
import CustomerInput from '@/components/CustomerInput.vue'
解决方式如下:
- 在挂载选项中注册对应的组件
const wrapper = mount(CustomerInputNumber, {
components: {
'el-input': Input,
'CustomerInput': CustomerInput
}
});
其中,注册组件可以是自定义的模拟组件,也可以在测试用例中按需引入的第三方组件
import CustomerInput from '@/components/CustomerInput.vue'
const mockComponent = {
template: "<div><slot></slot></div>",
props: {
color: String
}
};
const wrapper = mount(CustomerInputNumber, {
components:{
'el-input': mockComponent,
'CustomerInput': CustomerInput
}
});
- 使用临时Vue实例全局注册组件
import {
createLocalVue } from '@vue/test-utils'
import {
Input } from 'element-ui'
const localVue = createLocalVue()
localVue.use(Input)
const wrapper = mount(CustomerInputNumber, {
localVue
});
2、在测试组件中直接使用node_modules中的文件
例如,在测试组件中,直接使用了node_modules中的Emitter组件。但是在Jest转译时,会默认将node_modules忽略,所以当测试用例执行到该行时,会因为获取不到导出的Emitter组件而报错。
在报错信息中,Jest给出的处理建议,是将Emitter组件所在目录加入到转译文件中,需要对Jest做如下配置&#x