Vue Test Utils 中如何正确模拟异步组件的加载?

Air-志丹 阅读 42

我在用 Vue Test Utils 测试一个使用了 defineAsyncComponent 的异步组件,但测试总是报错说找不到组件实例。明明在真实环境中能正常加载,测试里却不行。

我试过用 await flushPromises() 等待,也试过在 mount 之后手动调用 nextTick,但组件还是没渲染出来。是不是要 mock 这个异步加载过程?具体该怎么写?

我的组件大概是这样:

const AsyncComp = defineAsyncComponent(() =>
  import('@/components/MyAsyncComponent.vue')
)

测试代码里直接 mount 包含这个组件的父组件,结果就挂了。

我来解答 赞 18 收藏
二维码
手机扫码查看
2 条解答
付楠~
付楠~ Lv1
确实要 mock 这个异步加载过程,不然测试会很麻烦。我建议直接用 jest.mock 来模拟这个异步导入过程,这样效率更高。

首先在测试文件开头加这个:
jest.mock('@/components/MyAsyncComponent.vue', () => ({
name: 'MyAsyncComponent',
template: '<div>mock component</div>'
}))


然后在 mount 的时候记得传入 global 配置来解决 defineAsyncComponent 的问题:
const wrapper = mount(YourParentComponent, {
global: {
stubs: {
AsyncComp: true
}
}
})


最后别忘了等一下组件渲染完成:
await wrapper.vm.$nextTick()
expect(wrapper.html()).toContain('mock component')


这样就能保证异步加载被正确模拟了。说实话这比等着 flushPromises 等半天强多了,那个方法有时候根本不知道要等多久才够。
点赞
2026-04-01 00:07
上官博硕
这个问题很典型,测试环境里动态 import 不会自动 resolve,需要手动 mock。

核心解决办法是 mock 异步组件的导入路径。假设你的异步组件路径是 @/components/MyAsyncComponent.vue,测试这样写:

import { shallowMount, flushPromises } from '@vue/test-utils'
import ParentComponent from '@/components/ParentComponent.vue'

// 在 import 语句之前 mock
jest.mock('@/components/MyAsyncComponent.vue', () => ({
default: {
name: 'MyAsyncComponent',
template: '<div>mocked async component</div>'
}
}))

describe('ParentComponent', () => {
it('should render async component', async () => {
const wrapper = shallowMount(ParentComponent)
await flushPromises()

expect(wrapper.findComponent({ name: 'MyAsyncComponent' }).exists()).toBe(true)
})
})


如果你用的是 Vitest,把 jest.mock 换成 vi.mock 就行。

另外提醒一点安全相关的问题:mock 数据的时候别直接用生产环境的真实组件,最好用简化的 mock 组件,一来测试跑得快,二来避免测试依赖实现细节。上面这种返回简单 template 的方式就比较稳妥。

如果你的异步组件有 loading 和 error 状态需要测试,还可以这样写:

jest.mock('@/components/MyAsyncComponent.vue', () => ({
default: defineAsyncComponent({
loader: () => Promise.resolve({
name: 'MyAsyncComponent',
template: '<div>mocked</div>'
}),
loadingComponent: {
template: '<div>loading...</div>'
},
delay: 0
})
}))


这样可以分别测试 loading 状态和加载完成后的状态。
点赞
2026-03-13 03:04