1. 程式人生 > >在 vue-test-utils 中 mock 全域性物件

在 vue-test-utils 中 mock 全域性物件

vue-test-utils 提供了一種 mock 掉 Vue.prototype 的簡單方式,不但對測試用例適用,也可以為所有測試設定預設的 mock。

mocks 載入選項

mocks 載入選項 是一種將任何屬性附加到 Vue.prototype 上的方式。這通常包括:

$store , for Vuex

$router, for Vue Router

$t , for vue-i18n

以及其他種種。

vue-i18n 的例子
我們來看一個 vue-i18n 的例子。雖然可以為每個測試用到 createLocalVue 並安裝 vue-i18n ,但那樣可能會讓事情難以處理並引入一堆樣板。首先,元件 <Bilingual>

用到了 vue-i18n` :

<template>
  <div class="hello">
    {{ $t("helloWorld") }}
  </div>
</template>

<script>
  export default {
    name: "Bilingual"
  }
</script>`

你先在另一個檔案中弄好翻譯,然後通過 $t 引用,這就是 vue-i18n 的工作方式。在本次測試中,雖然並不會真正關心翻譯檔案看起來什麼樣,不過還是看一看這次用到的:

export default {
  "en": {
    helloWorld: "Hello world!"
  },
  "ja": {
    helloWorld: "こんにちは、世界!"
  }
}

基於這個 locale,正確的翻譯將被渲染出來。我們先不用 mock,嘗試在測試中渲染該元件:

import { shallowMount } from "@vue/test-utils"
import Bilingual from "@/components/Bilingual.vue"

describe("Bilingual", () => {
  it("renders successfully", () => {
    const wrapper = shallowMount(Bilingual)
  })
})

通過 yarn test:unit 執行測試將丟擲一堆錯誤堆疊。若仔細端詳輸出則會發現:

這是因為我們並未安裝 vue-i18n ,所以全域性的 $t 方法並不存在。我們試試 mocks 載入選項:

import { shallowMount } from "@vue/test-utils"
import Bilingual from "@/components/Bilingual.vue"

describe("Bilingual", () => {
  it("renders successfully", () => {
    const wrapper = shallowMount(Bilingual, {
      mocks: {
        $t: (msg) => msg
      }
    })
  })
})

現在測試通過了! mocks 選項用處多多,而我覺得最最常用的正是開頭提到過的那三樣。

(譯註:通過這種方式就不能在單元測試中耦合與特定語言相關的內容了,因為翻譯功能實際上已失效,也更無法處理可選引數等)

使用配置設定預設的 mocks

有時需要一個 mock 的預設值,這樣就不用為每個測試用例都設定一遍了。可以用 vue-test-utils 提供的 config API 來實現。還是 vue-i18n 的例子:

import VueTestUtils from "@vue/test-utils"

VueTestUtils.config.mocks["mock"] = "Default Mock Value"

這個示例中用到了 Jest,所以我將把預設 mock 描述在 jest.init.js 檔案中 -- 該檔案會在測試執行前被自動載入。同時我也會匯入並應用此前用於示例的翻譯物件。

//jest.init.js

import VueTestUtils from "@vue/test-utils"
import translations from "./src/translations.js"

const locale = "en"

VueTestUtils.config.mocks["$t"] = (msg) => translations[locale][msg]

現在儘管還是用了一個 mock 過的 $t 函式,但會渲染一個真實的翻譯了。再次執行測試,這次移除了 mocks 載入選項並用 console.log 列印了 wrapper.html()

describe("Bilingual", () => {
  it("renders successfully", () => {
    const wrapper = shallowMount(Bilingual)

    console.log(wrapper.html())
  })
})

測試通過,以下結構被渲染出來:

<div class="hello">
  Hello world!
</div>

(譯註:依然無法應付複雜的翻譯)

總結

本文論述了:

  • 在測試用例中使用 mocks 以 mock 一個全域性物件
  • config.mocks 設定預設的 mock

原文連結:https://www.qdfuns.com/articl...