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.
Raccogliere le operazioni dell’API in un piccolo client
Prendiamo come esempio il pacchettoAcme\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().
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 inRequestException. Distinguile dalleConnectionExceptiondovute 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 inJsonException. 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.
Registrare il client nel service provider
Prepara la configurazione iniziale inconfig/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.
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.
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 veroCatalogClient 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.
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
- Documentazione ufficiale di Laravel: client HTTP
- Documentazione ufficiale di Laravel: sviluppo di pacchetti
- Framework v13.39.0: fake, createPendingRequest e __call della Factory
- Framework v13.39.0: configurazione e gestione degli stub di PendingRequest
- Framework v13.39.0: throw e decodifica JSON di Response
- Framework v13.39.0: destinazione di risoluzione e fake del facade Http
- Framework v13.39.0: registrazione singleton in FoundationServiceProvider
- Test ufficiali di Laravel: HttpClientTest