Плагины во Vue расширяют глобальное поведение приложения: добавляют
методы в app.config.globalProperties, регистрируют
директивы, компоненты, внедряют зависимости через
provide/inject, изменяют роутинг или состояние. В тестовой
среде такое поведение становится источником неявных зависимостей и
побочных эффектов. Изоляция плагинов позволяет:
Vue Test Utils предоставляет инструменты для точечного подключения, подмены и отключения плагинов.
В Vue 3 плагины подключаются через опцию global.plugins
при монтировании компонента:
import { mount } from '@vue/test-utils'
import MyPlugin from '@/plugins/my-plugin'
mount(MyComponent, {
global: {
plugins: [MyPlugin]
}
})
Такой плагин будет установлен в тестовое приложение
(app), создаваемое Vue Test Utils. Это приложение полностью
изолировано от других тестов, но не изолировано внутри одного
теста, если плагин хранит состояние на уровне модуля.
Типичная ошибка — плагины с синглтон-состоянием:
// plugin.js
let counter = 0
export default {
install(app) {
app.config.globalProperties.$inc = () => ++counter
}
}
При последовательном запуске тестов значение counter
будет накапливаться, даже если каждый тест монтирует компонент заново.
Vue Test Utils не сбрасывает состояние модулей JavaScript.
Решения:
Правильный шаблон — плагин как функция, возвращающая объект установки:
export function createCounterPlugin() {
let counter = 0
return {
install(app) {
app.config.globalProperties.$inc = () => ++counter
}
}
}
В тесте:
import { createCounterPlugin } from '@/plugins/counter'
mount(MyComponent, {
global: {
plugins: [createCounterPlugin()]
}
})
Каждое монтирование получает полностью изолированное состояние.
Если компонент использует $router, $t,
$api или другие глобальные свойства, нет необходимости
подключать полноценный плагин. Vue Test Utils позволяет напрямую
задавать globalProperties:
mount(MyComponent, {
global: {
config: {
globalProperties: {
$t: (key) => key
}
}
}
})
Такой подход:
Когда плагин сложный (Vue Router, Pinia, i18n), используется частичная или полная подмена.
Вместо реального роутера:
const mockRouter = {
push: vi.fn(),
currentRoute: {
value: { name: 'home' }
}
}
mount(MyComponent, {
global: {
config: {
globalProperties: {
$router: mockRouter,
$route: mockRouter.currentRoute.value
}
}
}
})
Компонент не знает, что работает с моком, а тест полностью контролирует поведение навигации.
Многие плагины используют provide. В тестах нет
необходимости устанавливать сам плагин — достаточно вручную задать
global.provide:
mount(MyComponent, {
global: {
provide: {
apiClient: {
get: vi.fn().mockResolvedValue({ data: [] })
}
}
}
})
Это особенно полезно для плагинов, работающих с сетью, аналитикой или хранилищем.
Плагины часто регистрируют глобальные директивы и компоненты. В тестах они изолируются локальной регистрацией:
mount(MyComponent, {
global: {
directives: {
focus: {
mounted: () => {}
}
}
}
})
или
mount(MyComponent, {
global: {
components: {
BaseButton: {
template: '<button><slot /></button>'
}
}
}
})
Полноценный плагин не требуется.
Иногда плагин нужен, но часть его поведения мешает тестам (таймеры, подписки, observers). Используется условная логика внутри плагина:
export default {
install(app, options = {}) {
if (options.disableTracking) return
// обычная логика
}
}
В тесте:
mount(MyComponent, {
global: {
plugins: [[MyPlugin, { disableTracking: true }]]
}
})
Vue Test Utils поддерживает передачу опций плагина в массиве.
Для полной изоляции важно:
vi.resetAllMocks());window и document без
явной необходимости;Каждый тест должен сам описывать своё окружение через
mount.
Если компонент можно протестировать без плагина — плагин не должен подключаться. Vue Test Utils позволяет эмулировать любую часть глобального окружения точечно, без установки реальной зависимости. Это делает тесты детерминированными, читаемыми и устойчивыми к изменениям инфраструктуры приложения.