Wie verspotte ich HTTP-Anfragen für PHPUnit?

7

Ich schreibe ein Plugin, das Anfragen an die Facebook-Grafik-API stellt. Wie würde ich das überwinden, da ich nicht möchte, dass meine Komponententests diese Anforderungen tatsächlich stellen? Meine Methode ruft sowohl wp_remote_getund auf wp_remote_post. Searching es scheint ein Weg , um Funktionen zu verspotten mit runkit, hier

Ich möchte vermeiden, dass Mitwirkende zu viele Abhängigkeiten benötigen, und möchte daher die oben beschriebene Methode vermeiden. Gibt es noch andere Möglichkeiten? Meine Klasse erweitert das, WP_UnitTestCasealso hoffe ich, dass es vielleicht etwas aus den wp-Unit-Tests gibt, das ich verwenden könnte?

Daithí
quelle

Antworten:

13

Wenn Sie sich ansehen WP_HTTP->request()(welche alle zugehörigen Funktionen umschließen), bietet es einen Filter-Hook zum Überschreiben einer Anforderung zugunsten der Rückgabe beliebiger Daten als Antwort:

// Allow plugins to short-circuit the request
$pre = apply_filters( 'pre_http_request', false, $r, $url );
if ( false !== $pre )
    return $pre;
Selten
quelle
2

Nehmen Sie die Ergebnisse einer gültigen oder ungültigen Anforderung, serialisieren Sie sie in Zeichenfolgen und fügen Sie dann Code hinzu, der die Zeichenfolge wieder in die Variable serialisiert, anstatt die Anforderung auszuführen.

Otto
quelle
2

Um Ihren Code weiter zu isolieren, würde ich die wp_remote_getetc-Aufrufe in eine Schnittstelle mit zwei Implementierungen einbinden. Eine Implementierung ruft auf wp_remote_getund die andere gibt Testdaten zurück.

Die Verwendung eines Tools wie Runkit in dieser Situation umgeht das eigentliche Problem, das Sie haben: Ihr Code und die APIs sind zu eng miteinander verbunden, und ein Grad an Kapselung und Abstraktion wäre von Vorteil.

Tom J Nowell
quelle
2

Ich musste mich einige Male über die HTTP-Anforderungsfunktionen von WordPress lustig machen und entschied mich daher, ein Tool dafür zu erstellen: WP HTTP TestCase

Grundsätzlich bietet es eine einfache Möglichkeit, die verschiedenen Dinge zu tun, die in den anderen Antworten beschrieben wurden. Aus der Readme:

WP HTTP Testcase

PHPUnit-Testfall zum Testen von Code, der die WordPress- WP_Http Klasse verwendet.

Wenn Sie wp_remote_request()oder andere Wrapper für WP_Http Methoden in Ihrem Code verwenden, ist das Testen schwierig, insbesondere wenn der Remote-Server von Ihrer Testumgebung aus möglicherweise nicht erreichbar ist. Dieser Testfall löst dieses Problem, indem Sie Ihre Anforderungen an eine andere Hostadresse weiterleiten, einen zwischengespeicherten Satz von Antworten verwenden oder die Remote-Antworten einfach verspotten, indem Sie künstliche Antworten bereitstellen.

Installation

Sie können dieses Paket mit Composer installieren:

composer require --dev jdgrimes/wp-http-testcase:~1.1

Verwendungszweck

Um es in Ihrem Code zu verwenden, müssen Sie zuerst die wp-http-testcase.phpDatei in Ihre PHPUnit-Bootstrap-Datei aufnehmen. Wenn Sie die Host-Routing- und Antwort-Caching-Funktionen verwenden, müssen Sie WP_HTTP_TestCase::init()Ihre Bootstrap-Datei aufrufen .

In Ihren Tests WP_Httpmüssen Sie dann verlängern, WP_HTTP_TestCaseanstatt WP_UnitTestCasewie gewohnt.

Verspottende Antworten

Verwenden des Antwort-Caching

Wenn möglich, testen Sie am besten einen Scheinhost, um die Anforderungen zu bearbeiten. In einigen Fällen möchten oder müssen Sie die Anforderungen möglicherweise tatsächlich an den realen Server senden, und dies kann auch durchgeführt werden. Welche davon Sie tun, hängt von der Art der Anfragen ab und welche Nebenwirkungen sie auf den Empfängerhost haben.

Einrichten eines Testhosts

Wenn Sie beispielsweise ein Plugin testen, das Anforderungen an eine API stellt, die von einem anderen Plugin oder einer anderen Software bereitgestellt wird, möchten oder müssen Sie dies wahrscheinlich nicht auf einer Live-Site testen. Stattdessen können Sie eine Testsite einrichten oder einen lokalen Server verwenden, der Teil Ihrer Entwicklungsumgebung ist. Dort können Sie die Software installieren, die die Anfragen bearbeitet. Sobald dies erledigt ist, können Sie Ihre Tests für diese Test-Site wie folgt ausführen:

WP_HTTP_TC_HOST=localhost phpunit

Ersetzen Sie einfach durch localhostden Hostnamen des lokalen Servers. Beachten Sie, dass die WP_HTTP_TC_*Flags wie oben als PHP-Konstanten oder als Bash-Umgebungsvariablen definiert werden können. Letzteres hat Vorrang.

Caching aktivieren

Dies ist natürlich viel langsamer als die meisten anderen Komponententests, da die Anforderungen einige Zeit in Anspruch nehmen müssen. Hier kommt das Caching ins Spiel. Wenn das Caching aktiviert ist, wird die Antwort auf jede Anforderung beim ersten Ausführen zwischengespeichert, und die zwischengespeicherte Version wird in Zukunft verwendet. Dies bedeutet, dass Ihre Tests blitzschnell bleiben können.

Um das Caching zu aktivieren, fügen Sie dies einfach Ihrem Bootstrap hinzu:

define( 'WP_HTTP_TC_USE_CACHING', true );

Sie möchten wahrscheinlich auch das Verzeichnis angeben, in dem der Cache gespeichert werden soll WP_HTTP_TC_CACHE_DIR. Sie können mehrere Cache-Gruppen verwenden und mit ihnen zwischen ihnen wechseln WP_HTTP_TC_CACHE_GROUP.

Verwenden des Live-Hosts

Es gibt jedoch den zweiten Fall, in dem Sie keinen Testserver einrichten können. Ein Beispiel, in dem dies der Fall wäre, wäre, wenn Ihr Plugin Anforderungen an die von GitHub bereitgestellte API stellt. Abhängig von der Situation kann es möglich sein, die Anfragen tatsächlich an den "Live" -Empfänger zu richten. Das Hauptproblem ist wiederum, dass die Anforderungen dazu führen, dass die Tests lange dauern. Es besteht auch die Möglichkeit, dass auf die API in Ihrer Testumgebung nicht immer zugegriffen werden kann oder dass Ihre Tests die API zu stark belasten und Sie blockiert werden. Hier kann Ihnen das Caching helfen. Sie müssen Ihre Tests nur gelegentlich für die "Live" -API ausführen, und den Rest der Zeit können Sie mithilfe der zwischengespeicherten Antworten testen.

Künstliche Antworten liefern

Natürlich kann es vorkommen, dass es nicht möglich ist, einen Testserver zu erstellen, und es ist auch nicht möglich, ihn gegen den Live-Server auszuführen. In diesem Fall möchten Sie möglicherweise künstliche Antworten in Ihre Tests fest codieren. So können Sie das machen:

Bevor Sie den Code aufrufen, der die HTTP-Anforderung aufruft, müssen Sie die Funktion so einstellen, dass die Antworten wie folgt verspottet werden:

$this->http_responder = array( $this, 'mock_server_response' );

Der HTTP-Responderfunktion werden zwei Argumente übergeben, die Anforderungsargumente und die URL, für die die Anforderung bestimmt war.

protected function mock_server_response( $request, $url ) {
   return array( 'body' => 'Test response.' ); 
}

Eine vollständige Liste der $requestArgumente und und der Antwort finden Sie unter WP_Http::request()

JD
quelle
1

In einem (zwei) Wort (en): Mock Data. getMock()Genau dafür wurde PHPUnit verfügbar. Wie die anderen Antworten bereits perfekt beschworen haben ...

  • Wo Sie gültige Scheindaten erhalten (Otto) - stellen Sie sicher, dass Sie gelegentlich neue Daten abrufen
  • und wo die Daten abgefangen werden sollen (Rarst)
  • und welche Tools zu verwenden sind (TomJNowell)

… Es gibt nur noch das Problem, dass die Überprüfung Ihres lokalen SSL-Zertifikats möglicherweise fehlschlägt. WP wird mit einem Filter dafür geliefert:

add_filter( 'https_local_ssl_verify', '__return_false' );

Für weitere Informationen zur WP-HTTP-API möchten Sie möglicherweise diese Antwort , diese Antwort , diese Antwort von @Wyck und diese Antwort von @toscho untersuchen .

Kaiser
quelle