Vue 2+Jest单元测试遇import语法错误,求排查方案
问题
使用Jest进行Vue2单元测试时,遇到报错:
SyntaxError: Cannot use import statement outside a module
报错栈:
at ScriptTransformer._transformAndBuildScript (node_modules/@jest/transform/build/ScriptTransformer.js:537:17)
已尝试以下操作但未解决:
- 在package.json中添加
type:module - 在jest.config.js配置
transformIgnorePatterns - 给组件的script标签添加
module属性
当前环境基于Vue2跟进课程学习,相关代码如下:
package.json
{ "name": "jest-test", "version": "0.1.0", "private": true, "scripts": { "serve": "vue-cli-service serve", "build": "vue-cli-service build", "test:unit": "vue-cli-service test:unit", "lint": "vue-cli-service lint" }, "dependencies": { "axios": "^1.2.3", "core-js": "^3.6.5", "vue": "^2.6.11", "vuex": "^3.4.0" }, "devDependencies": { "@babel/preset-env": "^7.20.2", "@vue/cli-plugin-babel": "^4.1.2", "@vue/cli-plugin-eslint": "^4.1.2", "@vue/cli-plugin-unit-jest": "^4.1.2", "@vue/cli-plugin-vuex": "^4.1.2", "@vue/cli-service": "^4.1.2", "@vue/eslint-config-standard": "^5.1.2", "@vue/test-utils": "^1.0.3", "babel-eslint": "^10.1.0", "eslint": "^6.7.2", "eslint-plugin-import": "^2.20.2", "eslint-plugin-node": "^11.1.0", "eslint-plugin-promise": "^4.2.1", "eslint-plugin-standard": "^4.0.0", "eslint-plugin-vue": "^6.2.2", "node-sass": "^4.12.0", "sass-loader": "^8.0.2", "vue-template-compiler": "^2.6.11" } }
待测试组件(TodoTitle.vue)
<template> <div> {{ todo.title }} </div> </template> <script> import axios from "axios"; export default { data() { return { todo: {}, }; }, created() { this.fetchTodo(); }, methods: { async fetchTodo() { const { data } = await axios.get( "https://jsonplaceholder.typicode.com/todos/1" ); this.todo = data; }, }, }; </script>
测试代码(TodoTitle.spec.js)
import { shallowMount } from "@vue/test-utils"; import TodoTitle from "@/components/TodoTitle"; describe("TodoTitle Component", () => { test("rendering", () => { const wrapper = shallowMount(TodoTitle); console.log(wrapper); expect(wrapper.text()).toBe(""); }); });
解决方案
问题根源:axios@1.x版本默认输出ES模块,而Jest默认不会转译node_modules目录下的文件,导致无法识别import语句。结合Vue CLI 4的Jest配置,按以下步骤修复:
1. 移除package.json中的type:module
Vue CLI 4的Jest配置基于CommonJS规范,添加type:module会导致模块加载冲突,直接删除该配置项。
2. 配置jest.config.js
在项目根目录创建或修改jest.config.js,确保转译规则覆盖axios:
module.exports = { preset: '@vue/cli-plugin-unit-jest', transformIgnorePatterns: [ // 排除node_modules中除axios外的其他模块,确保axios被转译 '/node_modules/(?!axios)/' ], transform: { '^.+\\.vue$': 'vue-jest', '^.+\\.js$': 'babel-jest' } }
3. 配置babel.config.js
确保Babel预设正确适配Jest环境,修改babel.config.js:
module.exports = { presets: [ ['@vue/cli-plugin-babel/preset', { targets: { node: 'current' } }] ] }
4. 重新运行测试
执行npm run test:unit,此时Jest会转译axios模块,import语句可以正常识别。
额外优化:Mock axios避免网络请求
测试时建议Mock axios的请求,避免实际网络调用影响测试结果,修改测试代码:
import { shallowMount } from "@vue/test-utils"; import TodoTitle from "@/components/TodoTitle"; import axios from "axios"; // Mock axios.get jest.mock('axios', () => ({ get: jest.fn().mockResolvedValue({ data: { title: 'Mocked Todo Title' } }) })); describe("TodoTitle Component", () => { test("rendering", async () => { const wrapper = shallowMount(TodoTitle); // 等待异步请求完成 await wrapper.vm.$nextTick(); expect(wrapper.text()).toBe("Mocked Todo Title"); }); });
内容的提问来源于stack exchange,提问作者YESSS
相关产品推荐
相关产品推荐

