最新文章專題視頻專題問答1問答10問答100問答1000問答2000關(guān)鍵字專題1關(guān)鍵字專題50關(guān)鍵字專題500關(guān)鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關(guān)鍵字專題關(guān)鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
當前位置: 首頁 - 科技 - 知識百科 - 正文

對 Vue-Router 進行單元測試的方法

來源:懂視網(wǎng) 責(zé)編:小采 時間:2020-11-27 22:04:29
文檔

對 Vue-Router 進行單元測試的方法

對 Vue-Router 進行單元測試的方法:由于路由通常會把多個組件牽扯到一起操作,所以一般對其的測試都在 端到端/集成 階段進行,處于測試金字塔的上層。不過,做一些路由的單元測試還是大有益處的。 對于與路由交互的組件,有兩種測試方式: 使用一個真正的 router 實例 mock 掉 $route
推薦度:
導(dǎo)讀對 Vue-Router 進行單元測試的方法:由于路由通常會把多個組件牽扯到一起操作,所以一般對其的測試都在 端到端/集成 階段進行,處于測試金字塔的上層。不過,做一些路由的單元測試還是大有益處的。 對于與路由交互的組件,有兩種測試方式: 使用一個真正的 router 實例 mock 掉 $route

來更新一下 <NestedRoute>:

<template>
 <div>
 Nested Route
 <div class="username">
 {{ $route.params.username }}
 </div>
 </div>
</template>

現(xiàn)在報錯變?yōu)榱耍?/p>

tests/unit/NestedRoute.spec.js
  NestedRoute
    ✕ renders a username from query string (17ms)

  ● NestedRoute › renders a username from query string

    TypeError: Cannot read property 'params' of undefined

這是因為 $route  并不存在。 我們當然可以用一個真正的路由,但在這樣的情況下只用一個 mocks  加載選項會更容易些:

it("renders a username from query string", () => {
 const username = "alice"
 const wrapper = shallowMount(NestedRoute, {
 mocks: {
 $route: {
 params: { username }
 }
 }
 })

 expect(wrapper.find(".username").text()).toBe(username)
})

這樣測試就能通過了。在本例中,我們沒有做任何的導(dǎo)航或是和路由的實現(xiàn)相關(guān)的任何其他東西,所以 mocks  就挺好。我們并不真的關(guān)心 username  是從查詢字符串中怎么來的,只要它出現(xiàn)就好。

測試路由鉤子的策略

Vue Router 提供了多種類型的路由鉤子, 稱為 “navigation guards”。舉兩個例子如:

  • 全局 guards (router.beforeEach)。在 router 實例上聲明
  • 組件內(nèi) guards,比如 beforeRouteEnter。在組件中聲明
  • 要確保這些運作正常,一般是集成測試的工作,因為需要一個使用者從一個理由導(dǎo)航到另一個。但也可以用單元測試檢驗導(dǎo)航 guards 中調(diào)用的函數(shù)是否正常工作,并更快的獲得潛在錯誤的反饋。這里列出一些如何從導(dǎo)航 guards 中解耦邏輯的策略,以及為此編寫的單元測試。

    全局 guards

    比方說當路由中包含 shouldBustCache  元數(shù)據(jù)的情況下,有那么一個 bustCache  函數(shù)就應(yīng)該被調(diào)用。路由可能長這樣:

    //routes.js
    
    import NestedRoute from "@/components/NestedRoute.vue"
    
    export default [
     {
     path: "/nested-route",
     component: NestedRoute,
     meta: {
     shouldBustCache: true
     }
     }
    ]
    
    

    之所以使用 shouldBustCache  元數(shù)據(jù),是為了讓緩存無效,從而確保用戶不會取得舊數(shù)據(jù)。一種可能的實現(xiàn)如下:

    //router.js
    
    import Vue from "vue"
    import VueRouter from "vue-router"
    import routes from "./routes.js"
    import { bustCache } from "./bust-cache.js"
    
    Vue.use(VueRouter)
    
    const router = new VueRouter({ routes })
    
    router.beforeEach((to, from, next) => {
     if (to.matched.some(record => record.meta.shouldBustCache)) {
     bustCache()
     }
     next()
    })
    
    export default router
    
    

    在單元測試中,你可能想導(dǎo)入 router 實例,并試圖通過 router.beforeHooks[0]()  的寫法調(diào)用 beforeEach;但這將拋出一個關(guān)于  next  的錯誤 -- 因為沒法傳入正確的參數(shù)。針對這個問題,一種策略是在將 beforeEach  導(dǎo)航鉤子耦合到路由中之前,解耦并單獨導(dǎo)出它。做法是這樣的:

    //router.js
    
    export function beforeEach((to, from, next) {
     if (to.matched.some(record => record.meta.shouldBustCache)) {
     bustCache()
     }
     next()
    }
    
    router.beforeEach((to, from, next) => beforeEach(to, from, next))
    
    export default router
    
    

    再寫測試就容易了,雖然寫起來有點長:

    import { beforeEach } from "@/router.js"
    import mockModule from "@/bust-cache.js"
    
    jest.mock("@/bust-cache.js", () => ({ bustCache: jest.fn() }))
    
    describe("beforeEach", () => {
     afterEach(() => {
     mockModule.bustCache.mockClear()
     })
    
     it("busts the cache when going to /user", () => {
     const to = {
     matched: [{ meta: { shouldBustCache: true } }]
     }
     const next = jest.fn()
    
     beforeEach(to, undefined, next)
    
     expect(mockModule.bustCache).toHaveBeenCalled()
     expect(next).toHaveBeenCalled()
     })
    
     it("busts the cache when going to /user", () => {
     const to = {
     matched: [{ meta: { shouldBustCache: false } }]
     }
     const next = jest.fn()
    
     beforeEach(to, undefined, next)
    
     expect(mockModule.bustCache).not.toHaveBeenCalled()
     expect(next).toHaveBeenCalled()
     })
    })
    
    

    最主要的有趣之處在于,我們借助 jest.mock,mock 掉了整個模塊,并用 afterEach  鉤子將其復(fù)原。通過將 beforeEach  導(dǎo)出為一個已結(jié)耦的、普通的 Javascript 函數(shù),從而讓其在測試中不成問題。

    為了確定 hook 真的調(diào)用了 bustCache  并且顯示了最新的數(shù)據(jù),可以使用一個諸如 Cypress.io 的端到端測試工具,它也在應(yīng)用腳手架 vue-cli  的選項中提供了。

    組件 guards

    一旦將組件 guards 視為已結(jié)耦的、普通的 Javascript 函數(shù),則它們也是易于測試的。假設(shè)我們?yōu)?<NestedRoute>  添加了一個 beforeRouteLeave  hook:

    //NestedRoute.vue
    
    <script>
    import { bustCache } from "@/bust-cache.js"
    export default {
     name: "NestedRoute",
     beforeRouteLeave(to, from, next) {
     bustCache()
     next()
     }
    }
    </script>
    
    

    對在全局 guard 中的方法照貓畫虎就可以測試它了:

    // ...
    import NestedRoute from "@/compoents/NestedRoute.vue"
    import mockModule from "@/bust-cache.js"
    
    jest.mock("@/bust-cache.js", () => ({ bustCache: jest.fn() }))
    
    it("calls bustCache and next when leaving the route", () => {
     const next = jest.fn()
     NestedRoute.beforeRouteLeave(undefined, undefined, next)
    
     expect(mockModule.bustCache).toHaveBeenCalled()
     expect(next).toHaveBeenCalled()
    })
    
    

    這樣的單元測試行之有效,可以在開發(fā)過程中立即得到反饋;但由于路由和導(dǎo)航 hooks 常與各種組件互相影響以達到某些效果,也應(yīng)該做一些集成測試以確保所有事情如預(yù)期般工作。

    總結(jié)

    本文講述了:

  • 測試由 Vue Router 條件渲染的組件
  • 用 jest.mock  和 localVue  去 mock Vue 組件
  • 從 router 中解耦全局導(dǎo)航 guard 并對其獨立測試
  • 用 jest.mock  來 mock 一個模塊
  • 聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

    文檔

    對 Vue-Router 進行單元測試的方法

    對 Vue-Router 進行單元測試的方法:由于路由通常會把多個組件牽扯到一起操作,所以一般對其的測試都在 端到端/集成 階段進行,處于測試金字塔的上層。不過,做一些路由的單元測試還是大有益處的。 對于與路由交互的組件,有兩種測試方式: 使用一個真正的 router 實例 mock 掉 $route
    推薦度:
    標簽: VUE 的方法 對于
    • 熱門焦點

    最新推薦

    猜你喜歡

    熱門推薦

    專題
    Top