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

Vue组件单元测试:模拟window对象引发_history读取null错误

Vue Router单元测试控制台报错处理

场景说明

我有一个Vue组件,包含如下待单元测试的方法:

const close = () => {
  (window.open('', '_self').opener=window).close()
}

我的测试代码如下:

import { createRouter, createWebHistory } from "vue-router";

describe('test suite', async () => {
let router
let wrapper

beforeEach(async () => {
    router = createRouter({
        history: createWebHistory(),
        routes: routes
    })

    wrapper = mount(MyComponent, {
        global: {
            plugins: [router]
        }
    })
})

  test('window.close is called when btn is clicked', async () => {
    const windowSpy = vi.spyOn(window, 'open').mockReturnValue({
        close: vi.fn()
    })
    const btn = wrapper.find('[name="BTN_1"]')
    await btn.trigger('click')
    expect(windowSpy).toHaveBeenCalledOnce()
  })

})

测试成功通过,但控制台输出如下错误信息:

[Vue Router warn]: Unexpected error when starting the router: TypeError: Cannot read properties of null (reading '_history') at Window.get history [as history]

报错原因及解决方案

这个报错是因为单元测试环境(比如Vitest/Jest)是模拟的浏览器环境,没有真实的window.history对象,而createWebHistory()依赖该对象,导致初始化路由时出错。

方案一:改用内存历史(推荐)

使用createMemoryHistory()替代createWebHistory(),内存历史不依赖真实浏览器环境,完全适配单元测试场景:

import { createRouter, createMemoryHistory } from "vue-router";

beforeEach(async () => {
    router = createRouter({
        history: createMemoryHistory(), // 替换为内存历史模式
        routes: routes
    })

    wrapper = mount(MyComponent, {
        global: {
            plugins: [router]
        }
    })
})

方案二:手动模拟window.history

如果必须使用createWebHistory(),可以在测试前手动模拟window.history对象的必要属性:

beforeEach(async () => {
    // 模拟window.history的核心属性
    Object.defineProperty(window, 'history', {
        value: {
            _history: {},
            pushState: vi.fn(),
            replaceState: vi.fn()
        },
        writable: true
    })

    router = createRouter({
        history: createWebHistory(),
        routes: routes
    })

    wrapper = mount(MyComponent, {
        global: {
            plugins: [router]
        }
    })
})

优先选择方案一,内存历史模式能更好地隔离测试环境,避免不必要的浏览器API依赖。

内容的提问来源于stack exchange,提问作者demiglace

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 01:03:10