Configuration
Installation
npm install --save-dev jest # package.json: "scripts": { "test": "jest" } npx jest # lancer tous les tests npx jest --watch # relancer à chaque modification
Nommage des fichiers
*.test.jsFichiers de test (motif par défaut)
*.spec.jsMotif de test alternatif
__tests__/Répertoire de tests (découverte automatique)
Lancer des tests spécifiques
npx jest path/to/file.test.js npx jest --testNamePattern="adds" npx jest --verbose # sortie détaillée
Tests de base
Structure d'un test
describe("Calculator", () => { test("adds 1 + 2 to equal 3", () => { expect(add(1, 2)).toBe(3); }); });
test vs it
test("works correctly", () => { /* ... */ }); it("should work correctly", () => { /* ... */ }); // Les deux sont identiques ; "it" se lit comme de l'anglais
Ignorer et focaliser
test.skip()Ignorer ce test
test.only()Lancer uniquement ce test
describe.skip()Ignorer toute la suite
describe.only()Lancer uniquement cette suite
Matchers
Égalité
.toBe(val)Égalité stricte (===)
.toEqual(val)Égalité profonde (objets/tableaux)
.toStrictEqual(val)Profond + type + propriétés undefined
.not.toBe(val)Inverser tout matcher
Véracité
.toBeTruthy()Valeur truthy
.toBeFalsy()Valeur falsy
.toBeNull()Exactement null
.toBeUndefined()Exactement undefined
.toBeDefined()Pas undefined
Nombres
.toBeGreaterThan(n)Supérieur à n
.toBeLessThanOrEqual(n)Inférieur ou égal
.toBeCloseTo(0.3, 5)Comparaison de flottants (5 chiffres)
Chaînes, tableaux, objets
.toMatch(/regex/)La chaîne correspond à la regex
.toContain(item)Le tableau/itérable contient l'élément
.toHaveLength(n)Longueur du tableau/chaîne
.toHaveProperty(key, val)L'objet a la propriété
.toMatchObject(obj)L'objet contient le sous-ensemble
Tests asynchrones
async / await
test("fetches data", async () => { const data = await fetchData(); expect(data).toEqual({ id: 1 }); });
Promesses
test("resolves to data", () => { return expect(fetchData()) .resolves.toEqual({ id: 1 }); });
Rejets
test("rejects with error", async () => { await expect(fetchBad()) .rejects.toThrow("Not Found"); });
Exceptions
test("throws on invalid input", () => { expect(() => validate(null)).toThrow(); expect(() => validate(null)).toThrow("invalid"); });
Mocking
Fonctions mock
const fn = jest.fn(); fn("hello"); expect(fn).toHaveBeenCalledWith("hello"); expect(fn).toHaveBeenCalledTimes(1);
Valeurs de retour mock
const fn = jest.fn() .mockReturnValue(42) .mockReturnValueOnce(99); fn(); // 99 (premier appel) fn(); // 42 (appels suivants)
Mocker des modules
jest.mock("./api"); const { fetchUser } = require("./api"); fetchUser.mockResolvedValue({ name: "Alice" });
Matchers mock
.toHaveBeenCalled()Appelé au moins une fois
.toHaveBeenCalledTimes(n)Appelé exactement n fois
.toHaveBeenCalledWith(args)Appelé avec des arguments spécifiques
.toHaveBeenLastCalledWith(args)Le dernier appel avait ces arguments
Espions
Espionner des méthodes
const spy = jest.spyOn(Math, "random") .mockReturnValue(0.5); expect(Math.random()).toBe(0.5); spy.mockRestore(); // restaurer l'original
Espionner des méthodes d'objets
const obj = { greet: (n) => `Hi ${n}` }; const spy = jest.spyOn(obj, "greet"); obj.greet("Alice"); expect(spy).toHaveBeenCalledWith("Alice");
Snapshots
Tests de snapshot
test("renders correctly", () => { const tree = renderer.create().toJSON(); expect(tree).toMatchSnapshot(); });
Snapshots en ligne
test("formats name", () => { expect(formatName("alice")) .toMatchInlineSnapshot(`"Alice"`); });
Mettre à jour les snapshots
npx jest --updateSnapshot # mettre à jour tous npx jest --updateSnapshot --testNamePattern="renders"
Setup et teardown
Hooks de cycle de vie
beforeAll(() => { /* une fois avant tous les tests */ }); afterAll(() => { /* une fois après tous les tests */ }); beforeEach(() => { /* avant chaque test */ }); afterEach(() => { /* après chaque test */ });
Portée
describe("Database", () => { beforeEach(() => db.connect()); afterEach(() => db.disconnect()); test("reads data", () => { /* ... */ }); });

Les hooks dans un describe ne s'appliquent qu'à ce bloc

Configuration
jest.config.js
module.exports = { testEnvironment: "node", coverageThreshold: { global: { branches: 80, lines: 80 } }, };
Options courantes
testEnvironment"node" ou "jsdom" (DOM)
rootsRépertoires où chercher les tests
collectCoverageActiver le rapport de couverture
coverageDirectoryRépertoire de sortie pour la couverture
moduleNameMapperAlias de chemins (ex. préfixe @/)
transformTransformations de fichiers (Babel, TS, etc.)
setupFilesAfterFrameworkLancer la configuration avant chaque suite
Couverture
npx jest --coverage npx jest --collectCoverageFrom="src/**/*.js"
Modèles courants
Tester des appels API
jest.mock("./api"); test("loads users", async () => { api.getUsers.mockResolvedValue([{id: 1}]); const users = await loadUsers(); expect(users).toHaveLength(1); });
Mocks de timers
jest.useFakeTimers(); test("delays execution", () => { const cb = jest.fn(); setTimeout(cb, 1000); jest.advanceTimersByTime(1000); expect(cb).toHaveBeenCalled(); });
Tests paramétrés
test.each([ [1, 1, 2], [2, 3, 5], ])("add(%i, %i) = %i", (a, b, expected) => { expect(add(a, b)).toBe(expected); });
Matchers personnalisés
expect.extend({ toBeWithinRange(received, floor, ceil) { const pass = received >= floor && received <= ceil; return { pass, message: () => `expected ${received} in [${floor},${ceil}]` }; }});