由于路由通常会把多个组件牵扯到一起操作,所以一般对其的测试都在 端到端/集成 阶段进行,处于测试金字塔的上层。不过,做一些路由的单元测试还是大有益处的。
对于与路由交互的组件,有两种测试方式:
使用一个真正的 router 实例
mock 掉 $route 和 $router 全局对象
因为大多数 Vue 应用用的都是官方的 Vue Router,所以本文会谈谈这个。
创建组件
我们会弄一个简单的 <App>,包含一个 /nested-child 路由。访问 /nested-child 则渲染一个 <NestedRoute> 组件。创建 App.vue 文件,并定义如下的最小化组件:
<template>
<div id="app">
<router-view />
</div>
</template><script>
export default {
name: 'app'
}
</script>
<NestedRoute> 同样迷你:
<template>
<div>Nested Route</div>
</template><script>
export default {
name: "NestedRoute"
}
</script>
现在定义一个路由:
import NestedRoute from "@/components/NestedRoute.vue"export default [
{ path: "/nested-route", component: NestedRoute }
]
在真实的应用中,一般会创建一个 router.js 文件并导入定义好的路由,写出来一般是这样的:
import Vue from "vue"
import VueRouter from "vue-router"
import routes from "./routes.js"Vue.use(VueRouter)
export default new VueRouter({ routes })
为避免调用 Vue.use(…) 污染测试的全局命名空间,我们将会在测试中创建基础的路由;这让我们能在单元测试期间更细粒度的控制应用的状态。
编写测试
先看点代码再说吧。我们来测试 App.vue,所以相应的增加一个 App.spec.js:
import { shallowMount, mount, createLocalVue } from "@vue/test-utils"
import App from "@/App.vue"
import VueRouter from "vue-router"
import NestedRoute from "@/components/NestedRoute.vue"
import routes from "@/routes.js"const localVue = createLocalVue()
localVue.use(VueRouter)
describe("App", () => {
it("renders a child component via routing", () => {
const router = new VueRouter({ routes })
const wrapper = mount(App, { localVue, router })
router.push("/nested-route")
expect(wrapper.find(NestedRoute).exists()).toBe(true)
})
})
照例,一开始先把各种模块引入我们的测试;尤其是引入了应用中所需的真实路由。这在某种程度上很理想 — 若真实路由一旦挂了,单元测试就失败,这样我们就能在部署应用之前修复这类问题。










