web-dev-qa-db-ja.com

PHPUnitのHTTPリクエストをモックするにはどうすればいいですか?

私はFacebookのグラフAPIをリクエストするプラグインを書いています。私のユニットテストで実際にこれらの要求をしたくないので、どうすればこれを克服できますか?私のメソッドはwp_remote_getwp_remote_postの両方を呼び出します。そこを検索することはrunkitを使って関数を偽装する方法のようです/ ここ

貢献者があまりにも多くの依存関係を必要とするのを避けたいので、上記の方法は避けたいと思います。他に選択肢はありますか?私のクラスはWP_UnitTestCaseを拡張しているので、私はおそらく私が使うことができるwpユニットテストから何かがあるのを望みますか?

6
Daithí

WP_HTTP->request() (これはすべての関連関数がラップしています)を見ると、応答として任意のデータを返すことを優先して要求の作成をオーバーライドするためのフィルター・フックがあります。

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

有効または無効なリクエストから得られた結果を取得し、それらを文字列にシリアル化してから、リクエストを実行する代わりに文字列をシリアル化解除するコードを変数に追加します。

2
Otto

コードをさらに分離するために、wp_remote_get etc呼び出しを2つの実装を持つインターフェイスにラップします。一方の実装はwp_remote_getを呼び出し、もう一方の実装はテストデータを返します。

このような状況でrunkitなどのツールを使用すると、実際の問題を回避できます。つまり、コードとAPIが密接に関連しすぎているため、ある程度のカプセル化と抽象化が有益になります。

2
Tom J Nowell

1つの言葉で:モックデータ。 PHPUnitはそのためにgetMock()を利用可能にしました。他の答えはすでに完璧に召喚されているので…

  • 有効なモックデータを入手する場所(Otto) - 時々新鮮なデータを取得するようにしてください
  • どこでデータを傍受するのか(Rarst)
  • そしてどんなツールを使うべきか(TomJNowell)

…あなたのローカルSSL証明書の検証が失敗するかもしれないということだけが残っています。 WPには、そのためのフィルタが付属しています。

add_filter( 'https_local_ssl_verify', '__return_false' );

WP HTTP APIの詳細については、 この回答この回答@Wyckによる回答 および @toscho

1
kaiser

私は数回WordPressのHTTPリクエスト機能をモックする必要があったので、そのためのツールを作ることにしました: WP HTTP TestCase

基本的にそれは他の答えが概説したさまざまなことをする簡単な方法を提供します。 Readmeから:

WP HTTPテストケース

WordPressのWP_Httpクラスを使用するコードをテストするためのPHPUnitテストケース。

コード内でWP_Httpメソッドにwp_remote_request()または他のラッパーを使用すると、特にリモートサーバーがテスト環境からアクセスできない場合、テストが困難になります。このテストケースでは、リクエストを別の異なるホストアドレスにルーティングしたり、キャッシュされた一連のレスポンスを使用したり、あるいは人工的なレスポンスを提供してリモートレスポンスをモックしたりすることでこれを解決します。

Installation

このパッケージはcomposerを使ってインストールできます。

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

使用法

あなたのコードでそれを使うためには、あなたのPHPUnitブートストラップファイルに最初にwp-http-testcase.phpファイルを含める必要があります。ホストのルーティングとレスポンスのキャッシュ機能を使用する場合は、ブートストラップファイルでWP_HTTP_TestCase::init()を呼び出す必要があります。

次に、WP_Httpを含むテストでは、通常のようにWP_HTTP_TestCaseではなくWP_UnitTestCaseを拡張する必要があります。

モッキングレスポンス

レスポンスキャッシングの使用

テストの最良の方法は、可能ならば、リクエストを処理するためにモックホストを設定することです。場合によっては、実際のサーバーに要求を実際に送信する必要があるか、必要である可能性があります。これも実行できます。これらのどれをあなたがするかは、リクエストの性質、そしてそれらが受信側ホストにどのような副作用をもたらすかにかかっています。

テストホストの設定

たとえば、他のプラグインや他のソフトウェアによって提供されているAPIに要求を出すプラグインをテストしている場合は、おそらくライブサイトでこれをテストする必要はないか、または必要ではありません。代わりに、テストサイトを設定するか、開発環境の一部であるローカルサーバーを使用することができます。そこでリクエストを処理するソフトウェアをインストールすることができます。これが完了したら、次のようにそのテストサイトに対してテストを実行できます。

WP_HTTP_TC_Host=localhost phpunit

localhostをローカルサーバーのホスト名に置き換えるだけです。 WP_HTTP_TC_*フラグはPHP定数として、または上記のようなbash環境変数として定義できることに注意してください。後者が優先されます。

キャッシングを有効にする

もちろん、リクエストは少し時間がかかるため、他のほとんどのユニットテストよりもはるかに遅くなります。キャッシュが有効になると、各要求に対する応答は最初に実行されたときにキャッシュされ、キャッシュされたバージョンが将来使用されます。これはあなたのテストが速く超高速であり続けることができることを意味します。

キャッシングを有効にするには、これをブートストラップに追加するだけです。

define( 'WP_HTTP_TC_USE_CACHING', true );

WP_HTTP_TC_CACHE_DIRを使って、キャッシュを保存するディレクトリを指定したいと思うかもしれません。複数のキャッシュグループを利用して、WP_HTTP_TC_CACHE_GROUPを使ってそれらを切り替えることができます。

ライブホストを使用する

しかし、テストサーバーを設定できないという2番目のケースもあります。これが当てはまる例は、あなたのプラグインがGitHubによって提供されたAPIに要求をする場合です。状況に応じて、実際に「ライブ」受信者に要求を出すことは実行可能かもしれません。また主な問題は、リクエストによってテストが完了するまでに長い時間がかかることです。また、APIがテスト環境からアクセス可能であるとは限らない、またはテストがAPIを激しく打ってしまいブロックされる可能性もあります。これはキャッシュがあなたを助けることができるところです。たまに「ライブ」APIに対してテストを実行するだけでよく、それ以外の時間はキャッシュされた応答を使用してテストできます。

人工的な反応をする

もちろん、テストサーバーを作成することが不可能で、ライブサーバーに対して実行することも不可能な場合があります。この場合は、人工的な応答をテストにハードコーディングすることをお勧めします。これを行う方法は次のとおりです。

HTTPリクエストを呼び出すコードを呼び出す前に、次のようにレスポンスをモックするように関数を設定する必要があります。

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

HTTPレスポンダ関数は2つの引数、リクエスト引数とリクエストが意図されたURLを渡されます。

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

$requestおよびresponse引数の全リストについては、 WP_Http::request() を参照してください。

1
J.D.