v13.39.0. Zie HTTP-client voor de basisbediening en Packages testen voor het opzetten van de testomgeving.
Deel de Factory en maak elke keer een nieuwe PendingRequest
De HTTP-client van Laravel bestaat uit objecten met verschillende verantwoordelijkheden.FoundationServiceProvider registreert de Factory als singleton, en ook de Http-facade resolvet uit de container via dezelfde klassenaam. Daarom kun je in een gewone Laravel-applicatie ook de communicatie via een Factory die je uit de container ontvangt, verifiëren met Http::fake(). Een ontwerp dat de facade direct gebruikt is ook mogelijk, maar op deze pagina injecteren we de Factory om de afhankelijkheden expliciet te maken.
Gewone methoden voor requestinstellingen op de Factory, zoals baseUrl(), worden via __call() doorgestuurd naar een nieuwe PendingRequest. createPendingRequest() geeft de fake-callbacks en de beperking op stray requests mee zoals die op het moment van aanmaken gelden, en newPendingRequest() past de gedeelde middleware en gedeelde opties toe.
API-bewerkingen bundelen in een kleine client
Als voorbeeld nemen we het packageAcme\Catalog, dat producten ophaalt uit een fictieve catalogus-API. src/CatalogClient.php houdt alleen de Factory en de basis-URL vast, en het request wordt pas aangemaakt tijdens de uitvoering van product().
Accept-Language die bij de vorige aanroep is toegevoegd niet hangen, ook als je met dezelfde client eerst product(42, 'ja') en daarna product(42) aanroept. De gedeelde instellingen die de gebruikende applicatie op de Factory heeft ingesteld, worden nog steeds op elk request toegepast.
- Pas packagespecifieke instellingen toe op de nieuw aangemaakte PendingRequest. Vermijd het instellen van
Http::globalOptions()tijdens de initialisatie van het package, omdat dat ook ongerelateerde communicatie beïnvloedt. - Verzend niets in de constructor. Ontwerp het zo dat het resolven van de service, het starten van Artisan of het publiceren van configuratiebestanden op zichzelf geen verbinding met de externe API maakt.
throw()maakt van 4xx- en 5xx-responses eenRequestException. Onderscheid dit van eenConnectionExceptionbij verbindingsfouten of timeouts, en vervang een fout niet door een succeswaarde zoals een lege array.json(flags: JSON_THROW_ON_ERROR)maakt van ongeldige JSON eenJsonException. In het voorbeeld wordt alleen gecontroleerd of het een array is, dus valideer bij een echte API ook de verplichte velden en datatypen.
Registreren in de service provider
Zet de standaardinstellingen klaar inconfig/catalog.php van het package. Sla hier geen HTTP-clients of closures op, maar alleen waarden die in de configuratiecache kunnen worden opgeslagen.
src/CatalogServiceProvider.php merget de configuratie en geeft de gedeelde Factory mee wanneer de client wordt geresolved. De binding van de Factory zelf wordt niet overschreven.
config/acme-catalog.php naar de echte API. De catalog.example.test in het voorbeeld is een fictieve host voor de uitleg en voor fakes.
bind() gebruikt, maar als de kant die de client vasthoudt een singleton is, wordt die referentie niet elke keer opnieuw aangemaakt. Het is belangrijk om de taal, de authenticatiegegevens en het requestobject die specifiek zijn voor een aanroep niet in properties op te slaan. Zie Levenscyclusontwerp van packageservices voor details.
Het overschrijven van de configuratie en het vernieuwen van de cache bij een deploy worden behandeld in Configuratie van packages mergen en cachen. Beheer de basis-URL als betrouwbare applicatieconfiguratie en laat de bestemming niet vrij bepalen door de invoer van een request.
De echte client verifiëren met fakes
Als je de client zelf mockt, kun je niet controleren of de gedeelde Factory wordt gebruikt en of URL’s en headers correct worden opgebouwd. In de tests van het package resolve je de echteCatalogClient uit de container en fake je alleen de HTTP-responses.
Het volgende voorbeeld draait in de testomgeving van Orchestra Testbench. In setUp() van elke test wordt preventStrayRequests() ingeschakeld. In tests die communiceren stel je alleen voor de verwachte URL een response in en laat je een '*'-fallback weg, zodat ook fouten in de URL worden gedetecteerd.
assertSent() verifieert dat er minstens één overeenkomend request is. Combineer dit met assertSentCount() om onbedoelde extra verzendingen niet te missen. assertSentInOrder() verifieert het aantal en de volgorde, dus je kunt het ook gebruiken om de scheiding van status te controleren wanneer je dezelfde client meerdere keren achter elkaar gebruikt.
De guard wordt ingesteld na parent::setUp(). Deze test alleen kan dus geen communicatie tijdens het opstarten van de provider verifiëren, dus houd vast aan een ontwerp waarin registratie en opstarten geen communicatie veroorzaken.
Met fakes kun je de requests controleren die de client opbouwt, en de verwerking van de responses die je hebt klaargezet. Ze garanderen niets over de authenticatie van de echte service, TLS-verbindingen, werkelijke timeoutduur of wijzigingen in de specificatie van de externe API. Voer verificaties met externe verbindingen apart uit in een expliciet daarvoor ingerichte testomgeving.
Extra verificaties voor langdurig onderhoud
Als je de verantwoordelijkheden van de gedeelde Factory en elke PendingRequest scheidt, kan de gebruikende kant de gewone testmethoden van Laravel ongewijzigd gebruiken. Zorg eerst voor een implementatie die via de gedeelde Factory loopt en voor tests die dat controleren, in plaats van eerst een eigen fake-mechanisme te bouwen.
Geraadpleegde primaire bronnen
- Officiële Laravel-documentatie: HTTP Client
- Officiële Laravel-documentatie: Packageontwikkeling
- Framework v13.39.0: fake, createPendingRequest en __call van Factory
- Framework v13.39.0: instellingen en stubverwerking van PendingRequest
- Framework v13.39.0: throw en JSON-decodering van Response
- Framework v13.39.0: resolvedoel en fake van de Http-facade
- Framework v13.39.0: singletonregistratie in FoundationServiceProvider
- Officiële Laravel-tests: HttpClientTest