All posts

Testing Error Scenarios in Vue.js Applications

Write robust Vue.js error tests with Vitest, Vue Test Utils, component error boundary testing, and async error handling verification.

Testing Error Scenarios in Vue.js Applications

Vue's composition API and component model require specific testing patterns for error scenarios. Here's how to cover failure paths.

Component Error Tests with Vue Test Utils

import { mount } from '@vue/test-utils';
import { describe, it, expect, vi } from 'vitest';

describe('UserProfile', () => {
  it('shows error message when API fails', async () => {
    vi.spyOn(api, 'getUser').mockRejectedValue(new Error('Network error'));

    const wrapper = mount(UserProfile, {
      props: { userId: '123' },
    });

    await flushPromises();

    expect(wrapper.find('.error-message').text()).toBe('Failed to load profile');
    expect(wrapper.find('.user-data').exists()).toBe(false);
  });

  it('shows validation errors on invalid input', async () => {
    const wrapper = mount(UserForm);

    await wrapper.find('input[name="email"]').setValue('invalid');
    await wrapper.find('form').trigger('submit');

    expect(wrapper.find('.field-error').text()).toContain('valid email');
  });
});

Test Pinia Store Error Handling

import { setActivePinia, createPinia } from 'pinia';

describe('useOrderStore', () => {
  beforeEach(() => setActivePinia(createPinia()));

  it('sets error state on fetch failure', async () => {
    vi.spyOn(api, 'getOrders').mockRejectedValue(new Error('Server error'));

    const store = useOrderStore();
    await store.fetchOrders();

    expect(store.error).toBe('Server error');
    expect(store.orders).toEqual([]);
    expect(store.loading).toBe(false);
  });

  it('clears previous error on retry', async () => {
    const store = useOrderStore();
    store.error = 'Previous error';

    vi.spyOn(api, 'getOrders').mockResolvedValue([{ id: '1' }]);
    await store.fetchOrders();

    expect(store.error).toBeNull();
  });
});

Test Composable Error Handling

describe('useFetchData', () => {
  it('returns error state on failure', async () => {
    vi.spyOn(globalThis, 'fetch').mockRejectedValue(
      new TypeError('Failed to fetch')
    );

    const { data, error, loading } = useFetchData('/api/data');

    await flushPromises();

    expect(error.value).toBe('Failed to fetch');
    expect(data.value).toBeNull();
    expect(loading.value).toBe(false);
  });
});

Test Error Boundaries

it('error boundary catches child component errors', () => {
  const BrokenComponent = {
    setup() { throw new Error('Component crashed'); },
    template: '<div />',
  };

  const wrapper = mount(ErrorBoundary, {
    slots: { default: BrokenComponent },
  });

  expect(wrapper.find('.fallback-ui').exists()).toBe(true);
});

Pair your Vue test suite with Bugsly production monitoring. When Bugsly captures a new error pattern, write a test that reproduces it to prevent regression.

Try Bugsly Free

AI-powered error tracking that explains your bugs. Set up in 2 minutes, free forever for small projects.

Get Started Free