Vai al contenuto principale
Quando un pacchetto deve usare un’API esterna, occorre conciliare due esigenze: ereditare la configurazione del client HTTP gestito da Laravel e non trascinare la configurazione da una chiamata all’altra. Creare una Factory propria o conservare a lungo una richiesta non ancora inviata sono cause tipiche per cui i fake definiti dall’applicazione che usa il pacchetto non vengono applicati. Questa pagina esamina l’implementazione di Laravel Framework v13.39.0. Per le operazioni di base consulta Client HTTP, per la preparazione dell’ambiente di test consulta Testare i pacchetti.

Condividere la Factory e creare ogni volta una PendingRequest

Il client HTTP di Laravel è composto da oggetti con responsabilità diverse. FoundationServiceProvider registra la Factory come singleton, e anche il facade Http la risolve dal container usando lo stesso nome di classe. Per questo, in una normale applicazione Laravel, anche le comunicazioni effettuate tramite la Factory ricevuta dal container possono essere verificate con Http::fake(). È possibile anche usare direttamente il facade, ma in questa pagina iniettiamo la Factory per rendere esplicite le dipendenze. I normali metodi di configurazione della richiesta chiamati sulla Factory, come baseUrl(), vengono inoltrati da __call() a una nuova PendingRequest. createPendingRequest() passa le callback dei fake e il blocco delle stray request in vigore al momento della creazione, mentre newPendingRequest() applica i middleware comuni e le opzioni comuni.
Se all’interno del pacchetto crei new Factory() o il client di un’altra libreria HTTP, i fake della Factory condivisa e Http::preventStrayRequests() non vengono ereditati. Queste funzionalità non bloccano le comunicazioni dell’intero processo. Nei client pensati per Laravel usa la Factory condivisa; se fornisci un client indipendente, prepara un metodo di test dedicato a quel client.

Raccogliere le operazioni dell’API in un piccolo client

Prendiamo come esempio il pacchetto Acme\Catalog, che recupera prodotti da un’API di catalogo fittizia. src/CatalogClient.php conserva solo la Factory e l’URL di base, e la richiesta viene creata durante l’esecuzione di product().
Con questo design, anche se sullo stesso client chiami product(42) dopo product(42, 'ja'), l’header Accept-Language aggiunto nella chiamata precedente non rimane. La configurazione comune che l’applicazione ha impostato sulla Factory continua invece a essere applicata a ogni richiesta.
  • Applica la configurazione specifica del pacchetto alla PendingRequest appena creata. Evita di impostare Http::globalOptions() durante l’inizializzazione del pacchetto, perché influenzerebbe anche comunicazioni non correlate.
  • Non inviare nulla nel costruttore. Progetta il pacchetto in modo che la sola risoluzione del servizio, l’avvio di Artisan o la pubblicazione dei file di configurazione non si colleghino all’API esterna.
  • throw() trasforma le risposte 4xx e 5xx in RequestException. Distinguile dalle ConnectionException dovute a errori di connessione o timeout, e non sostituire un fallimento con un valore di successo come un array vuoto.
  • json(flags: JSON_THROW_ON_ERROR) trasforma un JSON non valido in JsonException. L’esempio verifica soltanto che il risultato sia un array, quindi con un’API reale verifica anche i campi obbligatori e i tipi di dato.
Se ti serve solo condividere URL di base o header, anche le macro HTTP della documentazione ufficiale sono un’opzione. Se invece il pacchetto fornisce le operazioni dell’API, il controllo dei valori di ritorno e il contratto delle eccezioni, separarli in una classe dedicata come questa rende la manutenzione più semplice. Per il funzionamento delle macro consulta Il trait Macroable.

Registrare il client nel service provider

Prepara la configurazione iniziale in config/catalog.php del pacchetto. Non salvarci client HTTP o closure, ma solo valori che possono essere memorizzati nella cache della configurazione.
src/CatalogServiceProvider.php unisce la configurazione e passa la Factory condivisa al momento della risoluzione del client. Il binding della Factory stessa non viene sovrascritto.
Il provider viene caricato, ad esempio, tramite la package discovery. Chi usa il pacchetto pubblica la configurazione e modifica l’URL di base in config/acme-catalog.php impostando l’API reale. L’host catalog.example.test dell’esempio è fittizio e serve per la spiegazione e per i fake.
Nell’applicazione il client si risolve tramite constructor injection o dal container. Solo con questa chiamata viene inviata la richiesta per recuperare il prodotto.
La registrazione usa bind(), ma se l’oggetto che conserva il client è un singleton, quel riferimento non viene ricreato ogni volta. L’importante è non salvare nelle proprietà la lingua, le credenziali o gli oggetti richiesta specifici di una chiamata. Per i dettagli consulta Progettare il ciclo di vita dei servizi di un pacchetto. La sovrascrittura della configurazione e l’aggiornamento della cache durante il deploy sono trattati in Unione e cache della configurazione dei pacchetti. Gestisci l’URL di base come configurazione affidabile dell’applicazione e non permettere che la destinazione venga scelta liberamente dall’input della richiesta.

Verificare il client reale con i fake

Se fai il mock del client stesso, non puoi verificare se usa la Factory condivisa né se costruisce correttamente URL e header. Nei test del pacchetto, risolvi dal container il vero CatalogClient e rendi fake solo le risposte HTTP. L’esempio seguente viene eseguito nell’ambiente di test di Orchestra Testbench. preventStrayRequests() viene attivato nel setUp() di ogni test. Nei test che comunicano, definendo risposte solo per gli URL previsti e senza un fallback '*', puoi rilevare anche errori negli URL.
Nel secondo test, il fake viene configurato dopo aver risolto il client. Poiché il client conserva la Factory e crea la PendingRequest al momento della chiamata effettiva, il fake viene applicato anche con questo ordine. Se modifichi il design per creare e conservare la PendingRequest nel costruttore, il test rileva che i fake aggiunti dopo la creazione non vengono applicati. assertSent() verifica che esista almeno una richiesta corrispondente. Per non lasciarti sfuggire invii aggiuntivi involontari, combinalo con assertSentCount(). assertSentInOrder() verifica numero e ordine delle richieste, quindi è utile anche per controllare l’isolamento dello stato quando si usa lo stesso client più volte di seguito. La guardia viene configurata dopo parent::setUp(). Questo test da solo non può verificare le comunicazioni durante l’avvio del provider, quindi mantieni un design in cui registrazione e avvio non comunicano.
Con i fake puoi verificare la richiesta costruita dal client e il modo in cui gestisce le risposte preparate. Non garantiscono l’autenticazione del servizio reale, la connessione TLS, i tempi di timeout effettivi né le modifiche alle specifiche dell’API esterna. Esegui separatamente le verifiche che richiedono connessioni esterne, in un ambiente di test preparato esplicitamente.

Verifiche da aggiungere per la manutenzione a lungo termine

Separando le responsabilità della Factory condivisa da quelle di ciascuna PendingRequest, chi usa il pacchetto può adottare così come sono i normali metodi di test di Laravel. Prima di costruire un meccanismo di fake proprio, prepara un’implementazione che passi dalla Factory condivisa e i test che lo verificano.

Fonti primarie consultate

Ultima modifica il 27 ottobre 2026