Конфигурация тестового окружения начинается с правильной установки и согласования зависимостей. Для тестирования Vue-компонентов в JavaScript обычно используется связка Vue Test Utils и тест-раннер (чаще всего Jest или Vitest).
Типовой набор зависимостей для проекта на Vue 3:
@vue/test-utilsvitest или jestjsdom@testing-library/jest-dom (опционально)vue-jest или @vitejs/plugin-vue (в
зависимости от сборщика)Установка через npm:
npm install -D @vue/test-utils vitest jsdom
Для проектов на Vite предпочтительнее Vitest, так как он использует ту же конфигурацию и плагинную систему.
vitest.config.jsКонфигурация Vitest максимально близка к Vite и обычно выглядит следующим образом:
import { defineConfig } from 'vitest/config'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
test: {
environment: 'jsdom',
globals: true,
setupFiles: './tests/setup.js',
include: ['**/*.spec.js']
}
})
Ключевые параметры:
jsdom необходим для
работы с DOM APIdescribe, it, expect без
импортовjest.config.jsДля Jest конфигурация более подробная:
module.exports = {
testEnvironment: 'jsdom',
moduleFileExtensions: ['js', 'json', 'vue'],
transform: {
'^.+\\.vue$': '@vue/vue3-jest',
'^.+\\.js$': 'babel-jest'
},
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/src/$1'
},
setupFilesAfterEnv: ['<rootDir>/tests/setup.js']
}
Особое внимание уделяется:
.vue файловsetup.js)Файл инициализации используется для глобальной конфигурации Vue Test Utils и тестовой среды.
Пример tests/setup.js:
import { config } from '@vue/test-utils'
import '@testing-library/jest-dom'
Через объект config можно задать глобальные
параметры:
config.global.stubs = {
transition: false,
teleport: true
}
config.global.mocks = {
$t: (key) => key
}
Основные сценарии использования:
<transition> и
<teleport>$router, $route,
$tVue Test Utils предоставляет объект config, влияющий на
поведение всех mount и shallowMount.
config.global.components = {
BaseButton,
Icon
}
Позволяет не регистрировать базовые компоненты в каждом тесте.
config.global.directives = {
focus: {
mounted(el) {
el.focus()
}
}
}
Полезно для директив, активно использующих DOM.
config.global.stubs = {
RouterLink: true,
RouterView: true
}
Снижает сложность тестов и изолирует компонент от роутинга.
Для корректной работы импортов в тестах алиасы должны совпадать с конфигурацией сборщика.
vite.config.jsimport { resolve } from 'path'
export default defineConfig({
resolve: {
alias: {
'@': resolve(__dirname, 'src')
}
}
})
Vitest автоматически использует эту конфигурацию.
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/src/$1'
}
Несоответствие алиасов приводит к ошибкам импорта и нестабильным тестам.
jsdom не реализует все браузерные возможности. Часто требуется ручное определение API.
Пример для ResizeObserver:
global.ResizeObserver = class {
observe() {}
unobserve() {}
disconnect() {}
}
Для matchMedia:
window.matchMedia = () => ({
matches: false,
addListener: () => {},
removeListener: () => {}
})
Такие моки размещаются в setup.js.
Тесты часто используют переменные окружения.
process.env.API_URL = 'http://localhost'
или через .env.test:
VITE_API_URL=http://localhost
Vitest автоматически подхватывает файлы окружения с соответствующим режимом.
process.env.NODE_ENV = 'test'
или через setupFiles.
test: {
coverage: {
reporter: ['text', 'html'],
exclude: ['node_modules/', 'tests/']
}
}
collectCoverage: true,
collectCoverageFrom: [
'src/**/*.{js,vue}',
'!src/main.js'
]
Покрытие позволяет контролировать качество тестов и выявлять неиспользуемый код.
Для крупных проектов конфигурацию целесообразно разбивать:
vitest.config.js — базоваяvitest.config.unit.js — юнит-тестыvitest.config.e2e.js — e2eПример:
export default defineConfig({
test: {
include: ['src/**/*.spec.js']
}
})
Это упрощает поддержку и масштабирование тестовой инфраструктуры.
Для улучшения автодополнения в Vitest:
/// <reference types="vitest" />
или в tsconfig.json:
{
"types": ["vitest/globals"]
}
Vue Test Utils также предоставляет типы для wrapper,
mount и VueWrapper, что особенно важно при
тестировании Composition API.
setup.js