# Мокаем глобальные объекты

vue-test-utils позволяет с лёгкостью мокать глобальные объекты, прикреплённые к Vue.prototype внутри теста, а также устанавливать стандартные значения мока для всех тестов.

Тест, использованный в последующем примере, можно найти здесь.

# Моки опции монтирования

Один из способов установить значение любого свойства из Vue.prototype – использовать моки опции монтирования. Обычно прототип включает в себя:

  • $store, для Vuex
  • $router, для Vue Router
  • $t, для vue-i18n

и множество других.

# Пример с vue-i18n

Примеры использования с Vuex и Vue Router описаны в соответствующих секциях: тут и тут. Давайте посмотрим на пример с vue-i18n. Использовать createLocalVue и устанавливать vue-i18n для каждого теста быстро надоест, а код будет шаблонный. Сперва сделаем компонент <Bilingual>, который использует vue-i18n:

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

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

vue-i18n работает следующим образом: вы пишите переводы в другом файле, а затем обращаетесь к ним через $t. Для данного теста не важно, как выглядит файл с переводом, пусть будет примерно такой:

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

Основываясь на локали, будет отрисовываться правильный перевод. Давайте попробуем отрендерить компонент, не используя моков в тесте.

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

describe("Bilingual", () => {
  it("Успешно отрисовывается", () => {
    const wrapper = shallowMount(Bilingual)
  })
})

Запуск тестов через yarn test:unit выдаст нам огромную трассировку стека. Если посмотреть внимательно, вы увидите:

[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("Успешно отрисовывается", () => {
    const wrapper = shallowMount(Bilingual, {
      mocks: {
        $t: (msg) => msg
      }
    })
  })
})

Теперь тест проходит проверку! Есть ещё много примеров использования опции mocks. Чаще всего я использую её для моков глобальных объектов, описанных выше.

# Установка стандартных моков, используя конфигурации

Иногда вам может понадобиться стандартное значение для мока, в таком случае не придётся создавать его для каждого теста. Вы можете сделать это, используя конфигурацию из vue-test-utils. Давайте расширим наш пример с vue-i18n. Вы можете устанавливать стандартные моки где угодно, сделав следующее:

import { config } from "@vue/test-utils"

config.mocks["mock"] = "Стандартное значение мока"

Демо проект для этого руководства использует Jest, поэтому я установлю стандартные моки в 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]

Теперь отрисуется настоящий перевод, несмотря на использование мока для функции $t. Запустим тест ещё, используя в этот раз console.log на wrapper.html(), а также уберём mocks из опции монтирования.

describe("Bilingual", () => {
  it("Успешно отрисовывается", () => {
    const wrapper = shallowMount(Bilingual)

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

Тест проходит проверку и отрисовывает следующую разметку:

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

Как использовать mocks при тестирования Vuex можно прочитать здесь. Техника одна и та же.

# Заключение

В этом руководстве обсудили:

  • как использовать mocks для моков глобальных объектов внутри тестов
  • как использовать config.mocks для установки стандартных значений для мока