Hai scritto una funzione, l'hai testata a mano in console.log, sembra funzionare, la mandi in produzione e dopo due giorni arriva la segnalazione: “non funziona quando l'input è negativo”. Lo vediamo ogni giorno nei progetti che ci arrivano: feature funzionanti in sviluppo, in produzione crollano. Il codice non testato è una promessa di bug. E per le PMI italiane che già lavorano con margini stretti, un bug in produzione significa clienti persi e ore di diagnostica.
Noi, di Meteora Web, testiamo tutto ciò che spediamo – backend Laravel, API REST, componenti Vue, logiche di business. Usiamo Jest da anni, sia su JavaScript che su TypeScript. In questa guida ti mostriamo come allestire un ambiente di test che non sia un peso, ma uno strumento che ti fa risparmiare tempo.
Perché Jest e non un altro framework
Jest è nato in Facebook (ora Meta) per testare React, ma oggi è il framework di testing più diffuso per JavaScript e TypeScript in assoluto. Funziona out-of-the-box: zero configurazione per progetti JS puri, e con poche righe per TypeScript. Rispetto a Mocha o Jasmine, offre integrazione nativa di mocking, coverage, e asserzioni – non devi installare Chai, Sinon, Istanbul separatamente. Vitest è più veloce in alcuni scenari, ma Jest ha una community più matura, plugin per ogni esigenza e una documentazione che copre ogni caso reale.
Sponsored Protocol
Quando scegliere Jest
Se lavori con Node.js, React, Vue, Angular o qualsiasi stack che produce JavaScript o TypeScript, Jest è la scelta più sicura. Se invece hai bisogno di test E2E, serve Playwright o Cypress; per unit e integration, Jest è perfetto.
Cosa puoi fare ora: decidi se il tuo progetto è puro JS o TypeScript, poi passa alla sezione successiva.
Configurare Jest per JavaScript e TypeScript
Installazione di base
npm install --save-dev jest
Aggiungi uno script in package.json:
"scripts": {
"test": "jest"
}
Jest cerca file in __tests__/ o file con estensione .test.js. Scrivi un primo test, ad esempio sum.test.js:
const sum = (a, b) => a + b;
test('somma 1 + 2 restituisce 3', () => {
expect(sum(1, 2)).toBe(3);
});
Lancia npm test e vedi il verde. Già funziona.
Configurare per TypeScript
Hai due strade: ts-jest (compila TS al volo) o @swc/jest (più veloce, ma meno feature). Noi usiamo ts-jest per la compatibilità totale con i tipi avanzati:
npm install --save-dev jest typescript ts-jest @types/jest
npx ts-jest config:init
Questo genera un file jest.config.js già pronto per TypeScript. Aggiungi un test in .test.ts:
Sponsored Protocol
import { sum } from './sum';
test('somma tipizzata', () => {
expect(sum(1, 2)).toBe(3);
});
Se usi @swc/jest, installa e crea un file .jestrc:
{
"transform": {
"^.+\\.(t|j)sx?$": ["@swc/jest"]
}
}
Cosa puoi fare ora: installa Jest e scrivi un test per una funzione che usi nel tuo progetto. Anche solo test('true is true', () => expect(true).toBe(true)) per verificare che l'ambiente funzioni.
Scrivere test che valgono il tempo speso
Describe, it, test
Organizza i test in blocchi logici con describe:
describe('funzione di calcolo sconto', () => {
it('applica 10% per ordini sopra 100€', () => {
expect(calcolaSconto(150)).toBe(135);
});
it('non applica sconto sotto 100€', () => {
expect(calcolaSconto(50)).toBe(50);
});
});
it e test sono sinonimi. Usa it per leggibilità.
Matcher fondamentali
toBe(value)— uguaglianza stretta (Object.is)toEqual(value)— uguaglianza profonda per oggetti e arraytoContain(item)— array o stringatoBeNull(),toBeUndefined(),toBeDefined()toBeTruthy(),toBeFalsy()toThrow(error)— per funzioni che lanciano eccezionitoHaveBeenCalled()— per mock (vedi prossimo capitolo)
Errore comune: usare toBe con oggetti. toBe confronta il riferimento, non i valori. Usa sempre toEqual per oggetti e array.
Sponsored Protocol
Mocking: isolare il codice reale
Il tuo codice chiama un'API esterna, legge da database o scrive su filesystem. Non vuoi che il test dipenda da servizi live. I mock sostituiscono quelle dipendenze con versioni controllate.
jest.fn()
Crea una funzione finta che puoi controllare:
const mockFn = jest.fn();
mockFn();
mockFn('arg1');
expect(mockFn).toHaveBeenCalledTimes(2);
expect(mockFn).toHaveBeenCalledWith('arg1');
Puoi anche specificare un valore di ritorno:
mockFn.mockReturnValue(42);
expect(mockFn()).toBe(42);
jest.mock()
Sostituisci un intero modulo:
jest.mock('axios');
import axios from 'axios';
axios.get.mockResolvedValue({ data: { id: 1 } });
Ogni funzione esportata da axios diventa un mock automatico.
jest.spyOn()
Spia un metodo esistente senza sostituirlo, poi puoi ripristinarlo:
const spy = jest.spyOn(console, 'log');
myFunction();
expect(spy).toHaveBeenCalledWith('hello');
spy.mockRestore();
Cosa puoi fare ora: prendi una funzione che nel tuo progetto chiama un'API esterna e scrivi un test che la mocka. Verifica che il comportamento sia corretto senza toccare il server.
Test asincroni
JavaScript è asincrono. Jest gestisce naturalmente Promise e async/await:
Sponsored Protocol
test('recupera dati utente', async () => {
const data = await fetchUser(1);
expect(data.name).toBe('Mario');
});
Se non restituisci la Promise, il test passa prima che l'operazione finisca. Sempre return o await.
Per testare rejection:
test('fallisce con errore', async () => {
await expect(fetchUser(-1)).rejects.toThrow('ID non valido');
});
Cosa puoi fare ora: trasforma un test sincrono che chiama una funzione asincrona – assicurati di usare await o return.
Coverage del codice – quanto stai testando?
Jest include Istanbul per il coverage. Basta aggiungere --coverage:
npx jest --coverage
Genera una cartella coverage/ con report HTML. Metriche: linee, rami, funzioni, statements. Un coverage del 100% non è obbligatorio – meglio pochi test ben scritti che molti test che coprono solo i casi facili. Noi miriamo a > 80% di branch coverage per il codice critico (calcoli, validazioni, logica di business).
Puoi configurare una soglia minima in jest.config.js:
module.exports = {
coverageThreshold: {
global: {
branches: 80,
functions: 85,
lines: 90,
},
},
};
Integrazione in CI/CD
I test devono fallire la build prima che il bug arrivi in produzione. Su GitHub Actions, un semplice workflow:
Sponsored Protocol
name: Test
on: [push]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- run: npm test -- --coverage
Se un test fallisce, la PR non viene mergiata. Sul serio: noi lo vediamo come una regola ferrea. Nessun deplo senza test verdi.
Cosa puoi fare ora: aggiungi un badge di coverage nel README del tuo repository e configuralo su GitHub Actions.
In sintesi — cosa fare adesso
- Installa Jest con
npm install --save-dev jestoyarn add --dev jest. - Configura TypeScript se usi TS:
npm install --save-dev ts-jest @types/jeste lancianpx ts-jest config:init. - Scrivi un test per la funzione più semplice del tuo progetto: un formato data, un calcolo di sconto, una validazione.
- Mocka le dipendenze esterne per rendere i test veloci e indipendenti.
- Imposta la soglia di coverage e blocca la build se sotto l'80%.
I test non sono un extra. Sono la rete di sicurezza che ti permette di modificare il codice senza paura. Noi, di Meteora Web, non spediamo una riga senza test. Inizia oggi: il tuo futuro te (e i tuoi clienti) ti ringrazieranno.