Simuler les appels API dans les tests Vue avec Vitest
Les composants Vue vivent rarement de manière isolée. La plupart d’entre eux récupèrent des données, soumettent des formulaires ou interrogent des endpoints. Lorsque vous testez ces composants sans contrôler le réseau, vos tests deviennent lents, instables et dépendants de services externes. Simuler les appels API dans les tests Vue permet d’éliminer ces problèmes en vous donnant le contrôle sur les réponses que vos composants reçoivent.
Cet article couvre deux stratégies pratiques pour simuler les API Vue avec Vitest : remplacer directement le module API avec vi.mock, et intercepter les requêtes au niveau de la couche HTTP en utilisant Mock Service Worker (MSW). Vous apprendrez également la gestion asynchrone spécifique à Vue qui rend ces deux approches fiables.
Points clés à retenir
- Les appels réseau réels dans les tests produisent des résultats instables, lents et non déterministes — la simulation vous donne un contrôle total sur les réponses.
vi.mockremplace le module API au niveau de l’import, ce qui le rend idéal pour des tests unitaires rapides et isolés.- MSW intercepte les requêtes au niveau de la couche réseau, permettant à votre logique fetch ou axios réelle de s’exécuter pour des tests d’intégration plus réalistes.
flushPromises()de@vue/test-utilsest généralement nécessaire lorsque les composants attendent des requêtes asynchrones avant de mettre à jour le DOM.
Pourquoi vous devez simuler les appels API dans les tests de composants Vue avec Vitest
Les appels réseau réels dans les tests produisent des résultats non déterministes. Le même test peut réussir localement et échouer en CI simplement parce qu’une API externe est lente ou indisponible. La simulation vous donne le contrôle sur ce que le réseau renvoie, afin que vos tests restent rapides et prévisibles.
Stratégie 1 : Simuler le module API avec vi.mock
L’approche la plus directe consiste à remplacer le module responsable des appels HTTP avant même que votre composant ne le voie.
// quote.service.ts
export async function fetchQuote() {
const response = await fetch('https://api.example.com/quotes/random')
return response.json()
}
// QuoteCard.test.ts
import { mount, flushPromises } from '@vue/test-utils'
import { vi, test, expect } from 'vitest'
import { fetchQuote } from './quote.service'
import QuoteCard from './QuoteCard.vue'
// vi.mock est automatiquement remonté au-dessus des imports
vi.mock('./quote.service')
test('affiche une citation après le montage', async () => {
vi.mocked(fetchQuote).mockResolvedValue({
id: 1,
quote: 'Citation de test',
author: 'Testeur',
})
const wrapper = mount(QuoteCard)
// Attend que toutes les promesses en attente et les mises à jour du DOM se terminent
await flushPromises()
expect(wrapper.text()).toContain('Citation de test')
})
Un détail crucial : vi.mock est remonté en haut du fichier par Vitest, il s’exécute donc avant tout import. Il s’agit d’un comportement intentionnel documenté dans l’API de simulation Vitest. Cela signifie que vous pouvez importer en toute sécurité la fonction réelle et recevoir quand même la version simulée dans votre test.
L’appel à flushPromises() est souvent requis dans ce pattern. Les composants Vue qui récupèrent des données au montage mettent à jour leur DOM de manière asynchrone. Des utilitaires comme flushPromises garantissent que les promesses en attente se résolvent avant l’exécution des assertions, évitant ainsi que les tests n’effectuent des assertions sur des états de chargement.
Quand utiliser cette approche : Pour tester unitairement un composant ou un service spécifique de manière isolée, lorsque vous souhaitez un contrôle strict sur les valeurs de retour et le nombre d’appels.
Discover how at OpenReplay.com.
Stratégie 2 : MSW avec les tests Vue Vitest pour la simulation au niveau HTTP
Mock Service Worker intercepte les requêtes au niveau de la couche réseau plutôt que de remplacer les modules JavaScript. Cela rend vos tests plus réalistes car l’appel fetch ou axios réel s’exécute toujours — MSW l’intercepte simplement avant qu’il ne quitte le processus.
Installez MSW et configurez-le pour un environnement Node (par défaut pour Vitest) :
npm install -D msw
// test/server.ts
import { setupServer } from 'msw/node'
import { http, HttpResponse } from 'msw'
export const server = setupServer(
http.get('https://api.example.com/quotes/random', () => {
return HttpResponse.json({ id: 1, quote: 'Citation MSW', author: 'MSW' })
})
)
// QuoteCard.test.ts
import { mount, flushPromises } from '@vue/test-utils'
import { test, expect, beforeAll, afterEach, afterAll } from 'vitest'
import { server } from './test/server'
import QuoteCard from './QuoteCard.vue'
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }))
afterEach(() => server.resetHandlers())
afterAll(() => server.close())
test('affiche une citation récupérée via MSW', async () => {
const wrapper = mount(QuoteCard)
await flushPromises()
expect(wrapper.text()).toContain('Citation MSW')
})
flushPromises() peut toujours être nécessaire ici pour la même raison — le système de réactivité de Vue a besoin d’un tick pour appliquer les mises à jour du DOM après la résolution de la promesse.
Quand utiliser cette approche : Pour des tests de type intégration où vous souhaitez vérifier que votre composant fonctionne avec un comportement HTTP réaliste, ou lorsque plusieurs composants partagent le même endpoint. La documentation de Vitest elle-même recommande MSW pour la simulation au niveau des requêtes dans les environnements de test basés sur Node.
Choisir entre vi.mock et MSW
vi.mock | MSW | |
|---|---|---|
| Intercepte au niveau | Module | Réseau |
| Teste la logique fetch réelle | ❌ | ✅ |
| Contrôle par test | ✅ Facile | ✅ Via server.use() |
| Idéal pour | Tests unitaires | Tests d’intégration |
Conclusion
Les deux stratégies sont des outils valides pour simuler les appels API dans les tests Vue. Utilisez vi.mock lorsque vous souhaitez des tests unitaires rapides et isolés avec un contrôle précis sur les valeurs de retour. Utilisez MSW lorsque vous souhaitez que vos tests exercent le chemin de requête complet. Dans les deux cas, des utilitaires comme flushPromises() aident à garantir que Vue termine le rendu des mises à jour asynchrones avant l’exécution des assertions.
FAQ
Oui. De nombreuses équipes utilisent vi.mock pour des tests unitaires ciblés de composants individuels et MSW pour des tests d'intégration plus larges qui couvrent plusieurs composants ou services. Gardez-les dans des fichiers de test séparés pour éviter toute confusion sur la couche qui gère la simulation.
Vue peut encore afficher l'état de chargement lorsque votre assertion s'exécute. Si votre assertion correspond par hasard au texte de chargement, le test réussit par coïncidence. L'avertissement de la console signale généralement des rejets de promesses non gérés ou des awaits manquants. Appeler flushPromises après le montage de composants qui déclenchent des requêtes asynchrones aide à éviter ces problèmes de timing.
MSW intercepte au niveau de la couche réseau, il fonctionne donc avec n'importe quel client HTTP incluant axios, fetch et les bibliothèques construites par-dessus comme ky ou got. Votre choix de client HTTP n'affecte pas la façon dont MSW gère l'interception.
Avec vi.mock, appelez mockRejectedValue pour simuler une erreur asynchrone levée. Avec MSW, utilisez server.use à l'intérieur d'un test spécifique pour enregistrer un gestionnaire qui renvoie HttpResponse.json avec un code de statut 4xx ou 5xx. Les deux approches vous permettent de vérifier la gestion des erreurs de votre composant.
Gain Debugging Superpowers
Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers. Check our GitHub repo and join the thousands of developers in our community.