Vue Test Utils报错‘TypeError: inject is not a function’的解决方法
修复Nuxt插件在Vue测试中的
inject is not a function错误 问题背景
编写了一个Nuxt全局密码验证插件,业务组件中可正常使用,但编写单元测试时触发TypeError: inject is not a function错误。
插件代码(plugins/passwordValidation.js)
export default function ({ app }, inject) { inject('passwordValidation', (password, passwordForConfirming) => { const errors = [] // 验证逻辑省略 return errors }) }
组件使用示例
... <script> ... export default { ... watch: { password(newPassword, oldPassword) { this.passwordValidationWarnings = this.$passwordValidation( newPassword, this.passwordForConfirming ) }, ... } </script>
测试报错代码片段
测试中尝试用localVue.use()注册插件触发错误:
import { createLocalVue, shallowMount } from '@vue/test-utils' import Vuex, { Store } from 'vuex' import RegisterForm from '@/components/organisms/RegisterForm.vue' import passwordValidation from '@/plugins/passwordValidation.js' const localVue = createLocalVue() localVue.use(Vuex) localVue.use(passwordValidation) // 此处触发错误 describe('RegisterForm', () => { describe('When the registration succeeds', () => { beforeEach(() => { // 测试逻辑省略 wrapper = shallowMount(RegisterForm, { localVue, // 其他配置项 }) }) }) })
错误信息
FAIL test/components/organisms/RegisterForm.spec.js ● Test suite failed to run TypeError: inject is not a function 1 | export default function ({ app }, inject) { > 2 | inject('passwordValidation', (password, passwordForConfirming) => { | ^ 3 | const errors = []
错误原因
Nuxt插件与Vue原生插件的签名不兼容:
- Nuxt插件接收
({ app }, inject)参数,inject是Nuxt专属的全局挂载方法 - Vue Test Utils的
localVue.use()期望插件接收Vue构造函数作为参数,不会传入inject方法,因此触发报错
修复方案
方案一:手动模拟Nuxt的inject逻辑
直接将验证方法挂载到localVue的原型上,替代localVue.use():
import { createLocalVue, shallowMount } from '@vue/test-utils' import Vuex, { Store } from 'vuex' import RegisterForm from '@/components/organisms/RegisterForm.vue' import passwordValidation from '@/plugins/passwordValidation.js' const localVue = createLocalVue() localVue.use(Vuex) // 模拟Nuxt的inject方法,挂载到Vue原型 const mockInject = (key, fn) => { localVue.prototype[`$${key}`] = fn } // 调用Nuxt插件并传入模拟参数 passwordValidation({ app: {} }, mockInject) describe('RegisterForm', () => { // 原有测试逻辑保持不变 })
方案二:修改插件兼容双环境
调整插件代码,让它同时支持Nuxt环境和Vue测试环境:
// plugins/passwordValidation.js // 抽离核心验证函数 const passwordValidationFn = (password, passwordForConfirming) => { const errors = [] // 验证逻辑省略 return errors } // 兼容Nuxt和Vue测试环境的插件入口 export default function (context, inject) { // Nuxt环境:用inject挂载 if (inject) { inject('passwordValidation', passwordValidationFn) } // Vue测试环境:挂载到Vue原型 else if (context.prototype) { context.prototype.$passwordValidation = passwordValidationFn } }
修改后测试代码可正常使用localVue.use(passwordValidation)。
方案三:挂载组件时直接注入方法
无需注册插件,在shallowMount的mocks选项中直接注入验证方法:
import { createLocalVue, shallowMount } from '@vue/test-utils' import Vuex, { Store } from 'vuex' import RegisterForm from '@/components/organisms/RegisterForm.vue' // 单独导入核心验证函数 import { passwordValidationFn } from '@/plugins/passwordValidation.js' const localVue = createLocalVue() localVue.use(Vuex) describe('RegisterForm', () => { describe('When the registration succeeds', () => { beforeEach(() => { wrapper = shallowMount(RegisterForm, { localVue, mocks: { $passwordValidation: passwordValidationFn } }) }) }) })
注意:需要先修改插件代码,将核心验证函数单独导出:
// plugins/passwordValidation.js export const passwordValidationFn = (password, passwordForConfirming) => { const errors = [] // 验证逻辑省略 return errors } export default function ({ app }, inject) { inject('passwordValidation', passwordValidationFn) }
使用版本
- nuxt: 2.15.8
- @vue/test-utils: 1.3.0
- jest: 27.5.1
内容的提问来源于stack exchange,提问作者Unigiri
相关产品推荐
相关产品推荐

