Vitest+Nuxt环境测试NuxtImg组件报错:Nuxt instance is unavailable!
问题排查
你遇到的问题核心是NuxtImg组件内部依赖Nuxt运行时实例(通过useNuxt钩子),即便尝试stub组件,若stub方式不正确,组件内部初始化逻辑仍会触发对Nuxt实例的访问,进而抛出错误。
解决方案
方案1:修正组件Stub的大小写
Vue组件的stub名称需要与组件注册名严格匹配,NuxtImg采用PascalCase命名,修改测试中的stub配置:
const createWrapper = () => mountSuspended(Logo, { props: { alt: 'test', src: 'test', sizes: 'test', width: 20, height: 20, preset: 'card-list-logo', }, global: { // 使用PascalCase匹配组件名 stubs: { NuxtImg: true }, }, })
方案2:手动模拟NuxtImg组件
若简单stub仍不生效,可自定义模拟组件完全替换原组件逻辑:
import { mountSuspended } from 'nuxt-vitest/utils' import Logo from '~/components/product/Logo.vue' // 自定义模拟NuxtImg组件 const MockNuxtImg = { props: ['src', 'alt', 'width', 'height', 'sizes', 'preset'], template: '<img :src="src" :alt="alt" :width="width" :height="height" class="product-logo" />' } const createWrapper = () => mountSuspended(Logo, { props: { alt: 'test', src: 'test', sizes: 'test', width: 20, height: 20, preset: 'card-list-logo', }, global: { components: { NuxtImg: MockNuxtImg }, }, }) describe('Product list logo', () => { test('test', async () => { const wrapper = await createWrapper() console.log(wrapper.html()) // 可添加断言验证组件渲染结果 expect(wrapper.find('img.product-logo').exists()).toBe(true) }) })
方案3:注入Nuxt实例上下文
若需要保留NuxtImg部分逻辑,可手动创建并注入Nuxt实例到测试上下文:
import { mountSuspended } from 'nuxt-vitest/utils' import Logo from '~/components/product/Logo.vue' import { createNuxtInstance } from '@nuxt/kit' const createWrapper = async () => { // 创建空的Nuxt实例 const nuxt = await createNuxtInstance({ modules: [] }) return mountSuspended(Logo, { props: { alt: 'test', src: 'test', sizes: 'test', width: 20, height: 20, preset: 'card-list-logo', }, global: { provide: { nuxt // 注入Nuxt实例到组件上下文 } }, }) } describe('Product list logo', () => { test('test', async () => { const wrapper = await createWrapper() console.log(wrapper.html()) }) })
原Stub失效原因
nuxt-img是组件的kebab-case别名,但Vue组件注册时实际使用的是NuxtImg这个PascalCase名称。使用stubs: ['nuxt-img']无法正确匹配到目标组件,导致原NuxtImg组件仍被加载,触发对Nuxt实例的访问逻辑。
内容的提问来源于stack exchange,提问作者Gezzasa
相关产品推荐
相关产品推荐

