由于路由通常會把多個組件牽扯到一起操作,所以一般對其的測試都在 端到端/集成 階段進行,處于測試金字塔的上層。不過,做一些路由的單元測試還是大有益處的。
對于與路由交互的組件,有兩種測試方式:
使用一個真正的 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) })})照例,一開始先把各種模塊引入我們的測試;尤其是引入了應用中所需的真實路由。這在某種程度上很理想 -- 若真實路由一旦掛了,單元測試就失敗,這樣我們就能在部署應用之前修復這類問題。
可以在 <App> 測試中使用一個相同的 localVue,并將其聲明在第一個 describe 塊之外。而由于要為不同的路由做不同的測試,所以把 router 定義在 it 塊里。
新聞熱點
疑難解答
圖片精選