# Testare un componente asincrono senza setTimeout

Un componente asincrono si testa con findBy e await: il test attende il DOM che cambia. Un setTimeout scritto a mano produce attese arbitrarie.

> Pagina: https://ui.eneawork.it/blog/test-componenti-asincroni
> Markdown: https://ui.eneawork.it/blog/test-componenti-asincroni.md

*2026-11-01*

Un componente asincrono si testa con findBy e await: il test attende che il DOM cambi. Un setTimeout scritto a mano introduce attese arbitrarie e test instabili.

Il catalogo EneUI conta 111.985 componenti, 1.556 blocchi e 12.808 icone da 1.472 librerie, misurati da /api/stats il 1 novembre 2026. La cifra è letta dall'endpoint il giorno della pubblicazione, così il contesto del catalogo resta verificabile.

## La regola di base

In Testing Library findBy è waitFor più getBy: ripete la query ogni 50 ms fino a 1.000 ms. Se il dato arriva prima, il test prosegue subito; se non arriva, fallisce con la query che ha provato.

## Il test che vale come modello

import { render, screen } from "@testing-library/react"; test("mostra il totale quando la risposta arriva", async () => { vi.stubGlobal( "fetch", vi.fn(() => Promise.resolve({ ok: true, json: () => Promise.resolve({ total: 12 }) })), ); render(); expect(await screen.findByText("12")).toBeInTheDocument(); });

Lo stub sostituisce fetch, cioè il confine del componente: la logica interna resta quella vera, la rete sparisce. L'assert guarda il testo che l'utente vede, non lo stato interno.

## Tre errori frequenti

## Installazione

npm i -D vitest jsdom @testing-library/react @testing-library/jest-dom npx vitest run

Tutti i pacchetti sono MIT e girano su jsdom in locale: nessuna rete, nessun browser, stesso comando in CI.

## Record vivi nel catalogo

Tre record asincroni su cui scrivere l'attesa: spinner, ai-chat-input e agent-dock. Per esplorare per categoria parti da 111.985 componenti.

## La limitazione

Il test aspetta il DOM, non dimostra l'assenza di race: due richieste che tornano in ordine inverso possono passare lo stesso test. Il timeout predefinito di 1.000 ms, inoltre, su una CI lenta produce fallimenti che in locale non compaiono.

## Dove continuare

Il modello di test è in Testing Library: cinque test; l'attesa con Suspense è in Suspense; il fetch senza librerie è in data fetching senza librerie; il confronto misurato fra librerie è in librerie React 2026.

## FAQ

### Serve aspettare con setTimeout?

No. findBy ripete la query fino al timeout: il test prosegue appena il DOM cambia, senza attese fisse.

### Perché compare un warning su act?

Perché lo stato cambia fuori da un await. Avvolgi l'azione in await userEvent o in await waitFor.

### Meglio mockare fetch o il modulo?

fetch, cioè il confine. Mockando il modulo si testa il mock, non il componente.

### Posso alzare il timeout?

Sì, con configure({ asyncUtilTimeout: 3000 }) una volta nel setup. Meglio un valore globale che attese sparse nei test.

### Questi test provano che non ci sono race?

No. Provano che il DOM mostra il dato atteso in quell'ordine; le race si vedono con test ripetuti in browser reale.
