Vue3 Jest测试中导入nextTick等函数出现类型不存在错误
问题
在Jest测试中从Vue3导入nextTick及其他函数时,出现类型错误:
Property 'nextTick' does not exist on type 'typeof import("/Users/XXXXX/dev/XXXXX/src/XXXXX/packages/XXXXX/node_modules/vue/dist/vue")'
测试代码如下:
import * as vue from 'vue'; import useClassNames from './useClassNames'; describe('useClassNames', () => { it('render', async () => { const result = useClassNames([]); await vue.nextTick(); expect(result).toBe([]); }); });
实际运行时nextTick是存在的,Object.keys(vue)能查到该属性,但无论是全量导入、默认导入还是按需导入都会报类型错误,导入h等其他函数也有同样问题。
项目配置信息
已安装依赖
{ "version": "0.1.0", "private": false, "scripts": { "test-with-coverage": "COLLECT_TEST_COVERAGE=TRUE jest", "test": "jest" }, "engines": { "node": ">=14.0.0" }, "dependencies": { "vue": "^3.2.37" }, "devDependencies": { "@testing-library/dom": "^8.14.0", "@testing-library/jest-dom": "^5.16.4", "@testing-library/user-event": "^14.2.1", "@types/jest": "^27.0.2", "@types/jest-axe": "^3.5.4", "@types/node": "^16.11.6", "@typescript-eslint/eslint-plugin": "^4.28.3", "@typescript-eslint/parser": "^4.28.3", "@vitejs/plugin-vue": "2.3.3", "@vue/test-utils": "^2.0.0", "@vue/vue3-jest": "26.0.1", "babel-jest": "^26.6.3", "eslint": "^7.31.0", "eslint-plugin-jest": "^24.3.6", "eslint-plugin-prettier": "^3.4.0", "eslint-plugin-vue": "^9.1.1", "jest": "~26.6.3", "jest-axe": "^6.0.0", "prettier": "2.1.2", "sass": "^1.52.2", "ts-jest": "~26.3.0", "typescript": "4.0.8", "vite": "^2.9.10", "vue-tsc": "0.37.0" } }
Jest配置
const collectCoverage = process.env.COLLECT_TEST_COVERAGE === 'TRUE'; module.exports = { testEnvironment: 'jsdom', moduleDirectories: ['node_modules', 'src'], moduleFileExtensions: ['vue', 'ts', 'js'], moduleNameMapper: { '^@/(.*)$': '<rootDir>/src/$1', }, transform: { '^.+\\.vue$': '@vue/vue3-jest', '^.+\\.js$': 'babel-jest', '^.+\\.ts$': 'ts-jest', }, setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'], collectCoverage, collectCoverageFrom: ['src/{components,hooks}/**/*.{js,ts,vue}'], coverageReporters: ['html', 'text-summary'], coverageDirectory: '<rootDir>/coverage', coverageThreshold: { global: { statements: 80, branches: 80, functions: 80, lines: 80, }, }, };
tsconfig.json
{ "compilerOptions": { "target": "ESNext", "useDefineForClassFields": true, "module": "ESNext", "moduleResolution": "Node", "strict": true, "jsx": "preserve", "sourceMap": true, "resolveJsonModule": true, "isolatedModules": true, "esModuleInterop": true, "lib": [ "ESNext", "DOM", "dom.iterable" ], "skipLibCheck": true, "baseUrl": ".", "paths": { "@/*": ["src/*"] } }, "include": [ "src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue", "jest.setup.ts", ], "references": [ { "path": "./tsconfig.node.json" } ] }
tsconfig.node.json
{ "compilerOptions": { "composite": true, "module": "ESNext", "moduleResolution": "Node" }, "include": [ "vite.config.ts" ] }
解决方案
1. 修正Vue导入方式并调整断言逻辑
Vue3的ESM模块中,nextTick等工具函数是具名导出,直接按需导入即可,同时注意数组断言的正确写法:
import { nextTick } from 'vue'; import useClassNames from './useClassNames'; describe('useClassNames', () => { it('render', async () => { const result = useClassNames([]); await nextTick(); expect(result).toEqual([]); // 数组需用toEqual而非toBe,toBe是严格引用相等 }); });
2. 调整TypeScript模块解析配置
当前moduleResolution设为Node,对ESNext模块的解析存在兼容问题,修改为适配打包工具的配置:
在tsconfig.json的compilerOptions中更新:
"moduleResolution": "NodeNext", "allowSyntheticDefaultImports": true
若使用TypeScript 5.0+,推荐改用
"moduleResolution": "Bundler",更适配Vite的模块解析逻辑。
3. 强制Jest使用Vue的ESM版本
在Jest配置的moduleNameMapper中添加映射,避免导入到UMD版本:
moduleNameMapper: { '^@/(.*)$': '<rootDir>/src/$1', '^vue$': 'vue/dist/vue.esm-bundler.js' },
4. 升级依赖版本(可选)
当前ts-jest和@vue/vue3-jest版本较低,对应Jest 26,升级到适配Vue3的高版本可提升类型兼容性:
npm install ts-jest@^27.0.0 @vue/vue3-jest@^27.0.0 jest@^27.0.0 --save-dev
5. 临时检查Vue类型声明(可选)
若上述方法无效,可临时关闭tsconfig.json中的skipLibCheck,排查是否存在类型声明冲突:
"skipLibCheck": false
排查完成后建议重新开启,避免影响编译速度。
内容的提问来源于stack exchange,提问作者Bong2000
相关产品推荐
相关产品推荐

