Unit Test vs Integration Test
La base de la stratégie de test iOS : les tests unitaires qui isolent chaque composant, ou les tests d'intégration qui valident les interactions entre eux ? Comment construire correctement sa pyramide de tests ?
Un exécuteur de tests natif ESM/TS à la vitesse propre de Vite
13 ans de maturité, la valeur par défaut de React Native
Sur un nouveau projet basé sur Vite ou Nuxt, le choix par défaut devrait être Vitest : tu partages le même vite.config.js. Sur Next.js, la configuration reste séparée (le compilateur n'est pas Vite), mais tu obtiens le support natif ESM/TypeScript sans installer de package de transformation supplémentaire.
Mais si tu as une grande suite Jest fonctionnelle, en particulier dépendante de RN/Metro, le coût de la migration peut dépasser le gain. Choisis la troisième voie : écris les nouveaux tests en Vitest, laisse la suite existante en Jest — les deux peuvent cohabiter dans le même monorepo.
| Catégorie | Vitest 5 | Jest |
|---|---|---|
| Performance | 9/10 | 7/10 |
| Facilité d'apprentissage | 7/10 | 7/10 |
| Écosystème | 6/10 | 9/10 |
| Communauté | 6/10 | 9/10 |
| Marché de l'emploi | 6/10 | 8/10 |
| Pérennité | 9/10 | 6/10 |
// Vitest 5 - Test de la fonction de calcul du total du panier
// vitest.config.ts partage vite.config.ts ; aucune transformation supplémentaire requise
import { describe, it, expect, vi } from 'vitest'
import { calculateCartTotal } from './cart'
import { fetchDiscount } from './discount-api'
vi.mock('./discount-api')
describe('calculateCartTotal', () => {
// Vitest 5 : clearMocks est true par défaut, aucun appel de nettoyage supplémentaire requis
it('calculates the subtotal correctly without a discount code', () => {
const items = [
{ price: 129.9, qty: 2 },
{ price: 49.5, qty: 1 },
]
expect(calculateCartTotal(items)).toBeCloseTo(309.3, 2)
})
it('uses a conditional mock with vi.when for a valid discount code', async () => {
// Vitest 5 nouvelle API : comportement de mock différent selon l'argument
vi.when(fetchDiscount).calledWith('CART10').thenResolve({ percent: 10 })
vi.when(fetchDiscount).calledWith('INVALID').thenReject(new Error('invalid code'))
const items = [{ price: 100, qty: 1 }]
const total = await calculateCartTotal(items, 'CART10')
expect(total).toBeCloseTo(90, 2)
expect(fetchDiscount).toHaveBeenCalledWith('CART10')
})
it('throws an error for an invalid code', async () => {
vi.when(fetchDiscount).calledWith('INVALID').thenReject(new Error('invalid code'))
const items = [{ price: 100, qty: 1 }]
await expect(calculateCartTotal(items, 'INVALID')).rejects.toThrow('invalid code')
})
})
// Monorepo : vitest -p web --coverage (uniquement le projet 'web' + rapport de couverture)// Jest 30 - Test de la fonction de calcul du total du panier
// babel.config.js ou la chaîne de transformation ts-jest doit être configurée séparément
const { calculateCartTotal } = require('./cart')
const { fetchDiscount } = require('./discount-api')
jest.mock('./discount-api')
describe('calculateCartTotal', () => {
afterEach(() => {
jest.clearAllMocks() // N'est pas la valeur par défaut chez Jest, doit être appelé manuellement
})
it('calculates the subtotal correctly without a discount code', () => {
const items = [
{ price: 129.9, qty: 2 },
{ price: 49.5, qty: 1 },
]
expect(calculateCartTotal(items)).toBeCloseTo(309.3, 2)
})
it('uses mockResolvedValue for a valid discount code', async () => {
fetchDiscount.mockImplementation((code) => {
if (code === 'CART10') return Promise.resolve({ percent: 10 })
return Promise.reject(new Error('invalid code'))
})
const items = [{ price: 100, qty: 1 }]
const total = await calculateCartTotal(items, 'CART10')
expect(total).toBeCloseTo(90, 2)
expect(fetchDiscount).toHaveBeenCalledWith('CART10')
})
it('throws an error for an invalid code', async () => {
fetchDiscount.mockRejectedValue(new Error('invalid code'))
const items = [{ price: 100, qty: 1 }]
await expect(calculateCartTotal(items, 'INVALID')).rejects.toThrow('invalid code')
})
})
// jest --projects packages/web --coverage exécute uniquement le package 'web' dans le monorepoSur un nouveau projet basé sur Vite ou Nuxt, le choix par défaut devrait être Vitest : tu partages le même vite.config.js. Sur Next.js, la configuration reste séparée (le compilateur n'est pas Vite), mais tu obtiens le support natif ESM/TypeScript sans installer de package de transformation supplémentaire.
Mais si tu as une grande suite Jest fonctionnelle, en particulier dépendante de RN/Metro, le coût de la migration peut dépasser le gain. Choisis la troisième voie : écris les nouveaux tests en Vitest, laisse la suite existante en Jest — les deux peuvent cohabiter dans le même monorepo.
Non, pas à l'identique. Les deux sont activement développés en septembre 2026 : Vitest 5.0 (3 septembre 2026) et Jest 30.5.2 (18 septembre 2026). Sur les projets basés sur Vite et Nuxt, Vitest a une charge de configuration plus faible car il réutilise le pipeline de transformation de l'application elle-même ; Jest continue de dominer notamment sur React Native/Metro et les grandes bases de code existantes.