v13.39.0. Die Grundlagen finden Sie unter HTTP-Client, die Vorbereitung der Testumgebung unter Pakete testen.
Die Factory teilen, den PendingRequest jedes Mal neu erstellen
Der HTTP-Client von Laravel besteht aus Objekten mit unterschiedlichen Verantwortlichkeiten.FoundationServiceProvider registriert die Factory als Singleton, und auch die Fassade Http löst über denselben Klassennamen aus dem Container auf. Deshalb lässt sich in einer gewöhnlichen Laravel-Anwendung auch die Kommunikation über eine aus dem Container bezogene Factory mit Http::fake() überprüfen. Ein Entwurf, der die Fassade direkt nutzt, ist ebenfalls möglich, doch auf dieser Seite wird die Factory injiziert, um die Abhängigkeit explizit zu machen.
Gewöhnliche Methoden zur Anfragekonfiguration wie baseUrl() auf der Factory werden über __call() an einen neuen PendingRequest weitergeleitet. createPendingRequest() übergibt die zum Zeitpunkt der Erzeugung gültigen Fake-Callbacks und die Einschränkung für Stray Requests, und newPendingRequest() wendet die gemeinsame Middleware und die gemeinsamen Optionen an.
API-Operationen in einem kleinen Client bündeln
Als Beispiel dient das PaketAcme\Catalog, das Produkte aus einer fiktiven Katalog-API abruft. src/CatalogClient.php hält nur die Factory und die Basis-URL, und die Anfrage wird erst während der Ausführung von product() erstellt.
Accept-Language nicht erhalten, wenn Sie mit demselben Client nach product(42, 'ja') noch product(42) aufrufen. Gemeinsame Einstellungen, die die nutzende Anwendung an der Factory vorgenommen hat, werden weiterhin auf jede Anfrage angewendet.
- Paketspezifische Einstellungen wenden Sie auf den neu erstellten PendingRequest an. Vermeiden Sie es, bei der Initialisierung des Pakets
Http::globalOptions()zu setzen, da dies auch unbeteiligte Kommunikation beeinflusst. - Im Konstruktor wird nichts gesendet. Entwerfen Sie das Paket so, dass das bloße Auflösen des Service, das Starten von Artisan oder das Veröffentlichen der Konfigurationsdatei keine Verbindung zur externen API herstellt.
throw()macht aus 4xx und 5xx eineRequestException. Unterscheiden Sie diese von derConnectionExceptionbei Verbindungsfehlern oder Timeouts, und ersetzen Sie Fehler nicht durch Erfolgswerte wie ein leeres Array.json(flags: JSON_THROW_ON_ERROR)macht aus ungültigem JSON eineJsonException. Das Beispiel prüft nur, ob ein Array vorliegt, daher sollten Sie bei einer echten API auch Pflichtfelder und Datentypen validieren.
Im Service-Provider registrieren
Legen Sie inconfig/catalog.php des Pakets die Standardkonfiguration an. Speichern Sie hier keine HTTP-Clients oder Closures, sondern nur Werte, die im Konfigurations-Cache abgelegt werden können.
src/CatalogServiceProvider.php führt die Konfiguration zusammen und übergibt beim Auflösen des Clients die gemeinsame Factory. Das Binding der Factory selbst wird nicht überschrieben.
config/acme-catalog.php auf die tatsächliche API. catalog.example.test im Beispiel ist ein fiktiver Host für Erklärungen und Fakes.
bind() verwendet, doch wenn das Objekt, das den Client hält, ein Singleton ist, wird auch diese Referenz nicht jedes Mal neu erzeugt. Entscheidend ist, aufrufspezifische Sprache, Zugangsdaten und Anfrageobjekte nicht in Eigenschaften zu speichern. Details finden Sie unter Lebenszyklus von Paket-Services entwerfen.
Das Überschreiben der Konfiguration und das Aktualisieren des Caches beim Deployment werden unter Zusammenführen und Cachen der Paketkonfiguration behandelt. Verwalten Sie die Basis-URL als vertrauenswürdige Anwendungskonfiguration, und lassen Sie das Verbindungsziel nicht frei über Eingaben der Anfrage festlegen.
Den echten Client mit Fakes überprüfen
Wenn Sie den Client selbst mocken, können Sie nicht prüfen, ob er die gemeinsame Factory nutzt und URL und Header korrekt zusammensetzt. In den Tests des Pakets lösen Sie den echtenCatalogClient aus dem Container auf und ersetzen nur die HTTP-Antworten durch Fakes.
Das folgende Beispiel läuft in der Testumgebung von Orchestra Testbench. In setUp() jedes Tests wird preventStrayRequests() aktiviert. In Tests mit Kommunikation legen Sie nur für die erwartete URL eine Antwort fest und verzichten auf einen '*'-Fallback, sodass auch fehlerhafte URLs erkannt werden.
assertSent() prüft, dass mindestens eine passende Anfrage existiert. Kombinieren Sie es mit assertSentCount(), damit unbeabsichtigte zusätzliche Anfragen nicht übersehen werden. assertSentInOrder() prüft Anzahl und Reihenfolge und eignet sich daher auch, um die Zustandstrennung bei aufeinanderfolgender Nutzung desselben Clients zu überprüfen.
Der Schutz wird nach parent::setUp() eingerichtet. Mit diesem Test allein lässt sich nicht auch die Kommunikation während des Starts der Provider überprüfen, halten Sie daher an einem Entwurf fest, der bei Registrierung und Start nicht kommuniziert.
Mit Fakes lassen sich die vom Client zusammengesetzte Anfrage und die Verarbeitung der vorbereiteten Antworten prüfen. Authentifizierung beim echten Dienst, TLS-Verbindungen, tatsächliche Timeout-Dauern und Spezifikationsänderungen der externen API werden dadurch nicht garantiert. Überprüfungen mit externen Verbindungen führen Sie separat in einer ausdrücklich dafür vorbereiteten Testumgebung durch.
Zusätzliche Tests für die langfristige Wartung
Wenn Sie die Verantwortlichkeiten der gemeinsamen Factory und der einzelnen PendingRequests trennen, können Nutzer die gewohnten Testmethoden von Laravel unverändert verwenden. Statt zuerst einen eigenen Fake-Mechanismus zu bauen, sollten Sie eine Implementierung bereitstellen, die über die gemeinsame Factory läuft, sowie Tests, die dies bestätigen.
Verwendete Primärquellen
- Offizielle Laravel-Dokumentation: HTTP-Client
- Offizielle Laravel-Dokumentation: Paketentwicklung
- Framework v13.39.0: fake, createPendingRequest und __call der Factory
- Framework v13.39.0: Konfiguration und Stub-Verarbeitung von PendingRequest
- Framework v13.39.0: throw und JSON-Dekodierung von Response
- Framework v13.39.0: Auflösungsziel und fake der Http-Fassade
- Framework v13.39.0: Singleton-Registrierung im FoundationServiceProvider
- Offizielle Laravel-Tests: HttpClientTest