← Tutti gli articoli

API e helper

Simulare le risposte API intercettando fetch e XHR

Il backend non e pronto. Oppure e pronto, ma non puoi farlo restituire una lista vuota, un errore 500 e un ritardo di tre secondi a comando. Questo articolo mostra come intercettare fetch e XMLHttpRequest direttamente nel browser con una regola JS di JustZix, restituendo JSON falso cosi puoi costruire e testare il frontend contro qualsiasi scenario tu voglia.

Perche intercettare nel browser

La risposta abituale a "mi servono dati falsi" e un server di mock — MSW, json-server, uno stub nel tuo ambiente di sviluppo. Sono ottimi, e per un intero team sono la scelta giusta. Ma a volte vuoi qualcosa di piu leggero:

Una regola JS di JustZix vive nel browser, si applica per pattern di URL e non richiede alcuna modifica al progetto. Questa e la sua nicchia: mocking rapido, chirurgico e perfetto per cose usa-e-getta.

Avvolgere window.fetch

Il trucco centrale e sostituire window.fetch con una tua funzione che decide, per ogni richiesta, se simulare o lasciar passare. Esegui questo a document_start cosi e installato prima che qualsiasi codice dell'app chiami fetch:

// Save the original so we can fall through to the real network
const realFetch = window.fetch.bind(window);

// Your mock table: match by URL substring -> response factory
const mocks = [
  {
    match: '/api/user/profile',
    response: () => jsonResponse({ id: 1, name: 'Ada Lovelace', plan: 'pro' })
  },
  {
    match: '/api/orders',
    response: () => jsonResponse([])   // the empty-list edge case
  }
];

window.fetch = async (input, init) => {
  const url = typeof input === 'string' ? input : input.url;
  const hit = mocks.find(m => url.includes(m.match));
  if (hit) {
    console.log('[mock] intercepted', url);
    return hit.response();
  }
  return realFetch(input, init);   // not mocked -> real request
};

Costruire una Response sintetica

La tua app si aspetta un vero oggetto Response — chiamera .json(), controllera .ok, leggera .status. Il costruttore Response ti da tutto questo gratis:

// Helper: a 200 OK JSON response
function jsonResponse(data, status = 200) {
  return new Response(JSON.stringify(data), {
    status,
    headers: { 'Content-Type': 'application/json' }
  });
}

Poiche e una Response autentica, il codice che fa const r = await fetch(...); if (r.ok) return r.json(); funziona senza modifiche. E proprio questo il punto — l'app non riesce a distinguere la differenza.

Simulare la latenza

Le liste vuote e i percorsi felici sono facili. I bug vivono nel percorso lento: spinner che non spariscono mai, race condition, doppi invii. Aggiungi un ritardo prima di risolvere:

// A small sleep helper
const sleep = (ms) => new Promise(r => setTimeout(r, ms));

// In the mock table, await it before returning
{
  match: '/api/search',
  response: async () => {
    await sleep(3000);            // 3 seconds of "loading..."
    return jsonResponse({ results: [] });
  }
}

Simulare i codici di errore

Ora i percorsi infelici. Un 500, un 404, un 401 che dovrebbe rispedirti al login — restituiscili con lo status giusto cosi la tua gestione degli errori gira davvero:

// 500 Internal Server Error
{
  match: '/api/checkout',
  response: () => jsonResponse(
    { error: 'payment_gateway_timeout' },
    500
  )
}

// A network failure (fetch rejects, not resolves)
{
  match: '/api/flaky',
  response: () => Promise.reject(new TypeError('Failed to fetch'))
}

Nota la differenza: un 500 si risolve comunque con r.ok === false, mentre una connessione caduta viene rifiutata. Testa entrambi — le app spesso gestiscono uno e vanno in crash sull'altro.

Avvolgere XMLHttpRequest

Molto codice piu vecchio, e librerie come axios, usano ancora XMLHttpRequest sotto il cofano. L'intercettazione di fetch non li tocca. XHR e piu goffo da falsificare, ma un wrapper sottile copre il caso comune:

const RealXHR = window.XMLHttpRequest;

window.XMLHttpRequest = function () {
  const xhr = new RealXHR();
  const realOpen = xhr.open;
  let mockedUrl = null;

  xhr.open = function (method, url, ...rest) {
    if (url.includes('/api/legacy')) mockedUrl = url;
    return realOpen.call(this, method, url, ...rest);
  };

  const realSend = xhr.send;
  xhr.send = function (...args) {
    if (!mockedUrl) return realSend.apply(this, args);

    // Fake a successful response without hitting the network
    setTimeout(() => {
      Object.defineProperty(xhr, 'readyState', { value: 4 });
      Object.defineProperty(xhr, 'status', { value: 200 });
      Object.defineProperty(xhr, 'responseText', {
        value: JSON.stringify({ legacy: true })
      });
      xhr.onreadystatechange && xhr.onreadystatechange();
      xhr.onload && xhr.onload();
    }, 0);
  };

  return xhr;
};

Questo e volutamente minimale — copre onload / onreadystatechange con testo JSON, che e cio di cui ha bisogno il 90% del codice XHR. Se una libreria ispeziona getAllResponseHeaders() dovrai stubbare anche quello. A quel punto, onestamente, ricorri a un vero server di mock.

Quando usare invece un vero server di mock

L'intercettazione nel browser e lo strumento giusto per lavoro rapido, circoscritto e usa-e-getta. Passa a MSW o json-server quando:

Regola pratica: se il mock dovrebbe essere committato, usa un server. Se dovrebbe svanire quando disattivi una regola, usa JustZix.

Vedi anche

Smetti di aspettare il backend. Installa JustZix, inserisci un wrapper di fetch in una regola JS circoscritta e costruisci il frontend contro ogni scenario gia da oggi.

Valuta questo articolo

Nessuna valutazione — sii il primo.

Provalo tu stesso

Installa JustZix e incolla qualsiasi snippet di questo articolo. Due minuti da zero a una regola funzionante su tutti i tuoi dispositivi.

Ottieni JustZix

Funzionalità · Come funziona · Esempi · Casi d'uso