javascript / intermediate
Snippet
Mocking Injected Asynchronous Service Contracts in Vitest Component Specs
Unit testing Vue components reliant on asynchronous dependency injection requires mocking the provided service contract using typed Symbols. Combining Vitest mock implementations inside the global.provide mount options with flushPromises ensures all microtasks and async lifecycle calls resolve deterministically before DOM assertions.
snippet.js
javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import { describe, it, expect, vi } from 'vitest';import { mount, flushPromises } from '@vue/test-utils';import type { InjectionKey } from 'vue';import UserProfile from './UserProfile.vue';interface AuthServiceContract {fetchPermissions(userId: string): Promise<string[]>;}const AUTH_KEY: InjectionKey<AuthServiceContract> = Symbol('AUTH_KEY');describe('UserProfile Async Permissions', () => {it('renders resolved permissions after async injection completes', async () => {const mockAuthService: AuthServiceContract = {fetchPermissions: vi.fn().mockResolvedValue(['read:reports', 'write:drafts'])};const wrapper = mount(UserProfile, {props: { userId: 'usr_42' },global: {provide: {[AUTH_KEY as symbol]: mockAuthService}}});expect(wrapper.text()).toContain('Loading...');await flushPromises();expect(mockAuthService.fetchPermissions).toHaveBeenCalledWith('usr_42');expect(wrapper.findAll('[data-test="perm-item"]')).toHaveLength(2);});});
vue
Breakdown
1
const AUTH_KEY: InjectionKey<AuthServiceContract> = Symbol('AUTH_KEY');
Defines a unique typed injection key contract for decoupling the component from concrete implementations.
2
fetchPermissions: vi.fn().mockResolvedValue(['read:reports', 'write:drafts'])
Creates an async spy returning resolved permission claims within a simulated Promise.
3
global: { provide: { [AUTH_KEY as symbol]: mockAuthService } }
Injects the mocked service contract into the test wrapper's provide hierarchy.
4
await flushPromises();
Resolves all pending asynchronous microtasks and Promise queues before asserting component output.