在 vue-test-utils 中 mock 全局對象

vue-test-utils 提供了一種 mock 掉 Vue.prototype 的簡單方式,不但對測試用例適用,也能夠爲全部測試設置默認的 mock。javascript

mocks 加載選項

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

  • $store , for Vuexvue

  • $router , for Vue Routerjava

  • $t , for vue-i18nbash

以及其餘種種。app

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 運行測試將拋出一堆錯誤堆棧。若仔細端詳輸出則會發現:ui

[Vue warn]: Error in config.errorHandler: "TypeError: _vm.$t is not a function"複製代碼

這是由於咱們並未安裝 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

相關文章
相關標籤/搜索