Тестирование custom middleware в Vue-приложениях играет ключевую роль для обеспечения корректного поведения приложений на уровне маршрутизации, управления состоянием или обработки асинхронных операций до отображения компонентов. Vue Test Utils предоставляет мощные средства для изоляции компонентов и проверки их взаимодействия с middleware.
Custom middleware в контексте Vue обычно представляют собой функции, которые выполняются до или после перехода на маршрут или перед выполнением действия в компоненте. Middleware может проверять авторизацию, форматировать данные или перенаправлять пользователя. Типичный пример middleware:
export default function authMiddleware(to, from, next) {
if (!localStorage.getItem('token')) {
next('/login');
} else {
next();
}
}
Ключевой аспект тестирования — изоляция логики middleware от реальной навигации, что позволяет проверять поведение в контролируемой среде.
Vue Router позволяет использовать middleware через навигационные
охранники (beforeEach, beforeEnter) или
напрямую внутри компонентов:
const routes = [
{
path: '/dashboard',
component: Dashboard,
beforeEnter: authMiddleware
}
];
Для unit-тестирования middleware компонент можно смонтировать с Vue Test Utils и имитировать переход на маршрут.
Основной инструмент — функция mount или
shallowMount, позволяющая изолировать компонент. Для
проверки middleware важно:
$route) и
объект навигации ($router).next, чтобы
отслеживать переходы или предотвращение навигации.Пример теста авторизационного middleware:
import { shallowMount } from '@vue/test-utils';
import authMiddleware from '@/middleware/authMiddleware';
import Dashboard from '@/components/Dashboard.vue';
describe('authMiddleware', () => {
it('перенаправляет на /login при отсутствии токена', () => {
const next = jest.fn();
const to = {};
const from = {};
localStorage.removeItem('token');
authMiddleware(to, from, next);
expect(next).toHaveBeenCalledWith('/login');
});
it('пропускает навигацию при наличии токена', () => {
const next = jest.fn();
const to = {};
const from = {};
localStorage.setItem('token', '123');
authMiddleware(to, from, next);
expect(next).toHaveBeenCalledWith();
});
});
В этом примере middleware полностью изолирован от Vue Router, что позволяет тестировать его логику независимо от маршрутизатора.
Многие middleware выполняют асинхронные операции, например запрос к
API. Для корректного тестирования асинхронных middleware используется
async/await и мокирование HTTP-запросов через
jest.mock или msw.
Пример:
export default async function fetchUserMiddleware(to, from, next) {
try {
const response = await fetch('/api/user');
const user = await response.json();
if (!user.active) {
next('/inactive');
} else {
next();
}
} catch {
next('/error');
}
}
Тест с мокированием fetch:
global.fetch = jest.fn(() =>
Promise.resolve({
json: () => Promise.resolve({ active: false })
})
);
it('перенаправляет на /inactive при неактивном пользователе', async () => {
const next = jest.fn();
await fetchUserMiddleware({}, {}, next);
expect(next).toHaveBeenCalledWith('/inactive');
});
Иногда middleware изменяет состояние компонента или Vuex-хранилища. Для проверки можно использовать Vue Test Utils совместно с моками хранилища:
import { createStore } from 'vuex';
const store = createStore({
state() { return { user: null }; },
mutations: {
setUser(state, user) { state.user = user; }
}
});
const wrapper = shallowMount(Dashboard, {
global: { plugins: [store] }
});
// Проверка, что middleware вызвал мутацию
expect(store.state.user).toEqual({ id: 1, name: 'Alice' });
Такой подход позволяет убедиться, что middleware корректно взаимодействует с состоянием приложения.
jest.fn() для отслеживания вызовов
next или других колбэков.async/await и
flushPromises при необходимости.Для глубокого анализа поведения middleware полезно:
next.wrapper.vm.$nextTick() для ожидания
обновления реактивных свойств.Тщательное тестирование custom middleware повышает надежность маршрутизации и бизнес-логики приложения, предотвращает ошибки при переходах и позволяет уверенно модифицировать код без риска поломки критичных функций.