Vue Academy · Урок

Имитация композируемых модулей, хранилищ и API

vi.mock(), имитация useFetch, хранилищ Pinia и маршрутизатора в тестах

Урок 4 из 413 шагов

«Имитация композируемых модулей, хранилищ и API» — бесплатный урок Vue Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Vue Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Vue Academy содержит 4 уроков всего.

Зачем нужны моки

Модульные тесты должны изолировать тестируемый компонент. Реальные сетевые запросы, настоящие хранилища и тяжёлые композаблы делают тесты медленными и нестабильными. Мокирование заменяет эти зависимости управляемыми подставными реализациями.

vi.fn: функция-мок

vi.fn() создаёт отслеживаемую функцию. Вы можете проверить, как она была вызвана, и управлять возвращаемым ею значением. Это основа любого мокирования.

import { vi } from "vitest"

const onSave = vi.fn()
onSave("draft")
expect(onSave).toHaveBeenCalledWith("draft")
expect(onSave).toHaveBeenCalledTimes(1)

Настройка возвращаемых значений

Управляйте результатом имитируемой функции с помощью mockReturnValue (синхронный код) или mockResolvedValue (разрешённое обещание) для асинхронного кода.

const getId = vi.fn().mockReturnValue(42)
expect(getId()).toBe(42)

const fetchUser = vi.fn().mockResolvedValue({ name: "Ada" })
// await fetchUser() => { name: "Ada" }

Мокирование модуля-композабла

vi.mock(path) заменяет целый модуль. Передайте фабрику, возвращающую подставные экспортируемые значения. Используйте её, чтобы заменить композабл заглушкой и передать компоненту предсказуемые данные.

import { vi } from "vitest"

vi.mock("@/composables/useUser", () => ({
  useUser: () => ({
    user: { value: { name: "Ada" } },
    isLoading: { value: false },
  }),
}))

Поднятие vi.mock

Вызовы vi.mock поднимаются в начало файла до выполнения импортов. Поэтому фабрика не может обращаться к внешним переменным, объявленным позже: объявите вспомогательные элементы внутри фабрики или с помощью vi.hoisted.

// This runs before imports regardless of position.
vi.mock("@/api", () => ({ getPosts: vi.fn() }))

import { getPosts } from "@/api" // already the mock

Тестирование хранилищ Pinia

Компонентам, использующим хранилище Pinia, нужно хранилище в тестах. @pinia/testing предоставляет createTestingPinia, создающий хранилище, действия которого по умолчанию заменены заглушками.

// terminal: npm install -D @pinia/testing
import { createTestingPinia } from "@pinia/testing"

Подключение тестового хранилища Pinia

Передайте тестовое хранилище Pinia через глобальную опцию plugins при монтировании. Вы также можете задать начальное состояние.

import { mount } from "@vue/test-utils"
import { createTestingPinia } from "@pinia/testing"

const wrapper = mount(Profile, {
  global: {
    plugins: [createTestingPinia({
      initialState: { user: { name: "Ada" } },
    })],
  },
})

Проверка действий хранилища

По умолчанию действия заменяются заглушками и не выполняются, поэтому вы можете проверить, что они были вызваны. Получите хранилище и проверьте шпион.

import { useUserStore } from "@/stores/user"

const store = useUserStore()
await wrapper.get("button.logout").trigger("click")
expect(store.logout).toHaveBeenCalled()

Наблюдение за запросами

Вместо замены целого модуля можно наблюдать за глобальным объектом. vi.spyOn(global, "fetch") оборачивает настоящую функцию получения данных, чтобы вы могли переопределять её и проверять её вызовы.

const spy = vi.spyOn(global, "fetch").mockResolvedValue({
  ok: true,
  json: async () => ({ items: [1, 2, 3] }),
})

Полный тест получения данных

Имитируйте получение данных, вызовите действие, дождитесь разрешения обещаний, проверьте отображаемые данные и убедитесь, что запрос был выполнен с правильным URL.

it("loads items", async () => {
  vi.spyOn(global, "fetch").mockResolvedValue({
    ok: true,
    json: async () => ({ items: ["a", "b"] }),
  })
  const wrapper = mount(List)
  await flushPromises()
  expect(global.fetch).toHaveBeenCalledWith("/api/items")
  expect(wrapper.findAll("li")).toHaveLength(2)
})

Сброс моков между тестами

Общие моки накапливают историю вызовов. Сбрасывайте их в beforeEach (или включите clearMocks в конфигурации), чтобы один тест не влиял на другой.

import { beforeEach, vi } from "vitest"

beforeEach(() => {
  vi.clearAllMocks()
})

Быстрая проверка

Проверьте, насколько хорошо вы поняли мокирование.

Повторение

Вы научились заменять зависимости моками в тестах:

  • vi.fn() создаёт отслеживаемые функции; управляйте результатом с помощью mockReturnValue / mockResolvedValue.
  • vi.mock(path, factory) заменяет модуль (например, композабл); его вызов поднимается выше импортов.
  • createTestingPinia из @pinia/testing предоставляет хранилище с действиями-заглушками, вызовы которых можно проверять.
  • vi.spyOn(global, "fetch").mockResolvedValue(...) имитирует сетевые запросы.
  • Сбрасывайте моки между тестами с помощью vi.clearAllMocks().
Можно начать бесплатно

Изучай HTML с ИИ-репетитором — бесплатно

Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.

Курсы
42
Уроки
156

Часто задаваемые вопросы

Урок «Имитация композируемых модулей, хранилищ и API» бесплатный?

Да — полный текст урока «Имитация композируемых модулей, хранилищ и API» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Vue Academy, подпишись на CoddyKit PRO. Курс Vue Academy содержит 4 уроков всего.

Чему я научусь в уроке «Имитация композируемых модулей, хранилищ и API»?

vi.mock(), имитация useFetch, хранилищ Pinia и маршрутизатора в тестах Ты практикуешь Vue Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Vue Academy?

Предыдущий опыт не требуется. Vue Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.

Сколько времени занимает урок «Имитация композируемых модулей, хранилищ и API»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Vue Academy?

Да. Каждый урок Vue Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Настройка Vitest для проектов Vue
  2. Монтирование и поиск компонентов
  3. Тестирование взаимодействий пользователя и событий
  4. Имитация композируемых модулей, хранилищ и API
← Назад к Vue Academy