You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 22:01:27