メインコンテンツにスキップ

Mock API

はじめに

Web API は通常、HTTP エンドポイントとして実装されます。Playwright は、HTTP と HTTPS の両方のネットワークトラフィックをモックおよび変更するための API を提供します。ページが行うすべてのリクエスト ( XHRfetch リクエストを含む) は、追跡、変更、およびモックできます。Playwright を使用すると、ページによって行われた複数のネットワークリクエストを含む HAR ファイルを使用してモックすることもできます。

API リクエストのモック

次のコードは、*/**/api/v1/fruits へのすべての呼び出しをインターセプトし、代わりにカスタムレスポンスを返します。API へのリクエストは行われません。テストは、モックされたルートを使用する URL に移動し、モックデータがページに存在することを確認します。

// Intercept the route to the fruit API
page.route("https://fruit.ceo/api/breeds/image/random", route -> {
List<Dictionary<String, Object>> data = new ArrayList<Dictionary<String, Object>>();
Hashtable<String, Object> dict = new Hashtable<String, Object>();
dict.put("name", "Strawberry");
dict.put("id", 21);
data.add(dict);
// fulfill the route with the mock data
route.fulfill(RequestOptions.create().setData(data));
});

// Go to the page
page.navigate("https://demo.playwright.dev/api-mocking");

// Assert that the Strawberry fruit is visible
assertThat(page.getByText("Strawberry")).isVisible();

テスト例のトレースから、API が一度も呼び出されず、モックデータで処理されたことがわかります。api mocking trace

高度なネットワーキングの詳細をご覧ください。

API レスポンスの変更

場合によっては、API リクエストを行うことが不可欠ですが、再現性のあるテストを可能にするためにレスポンスを修正する必要があります。その場合、リクエストをモックする代わりに、リクエストを実行し、変更されたレスポンスで処理できます。

次の例では、フルーツ API への呼び出しをインターセプトし、'Loquat' という新しいフルーツをデータに追加します。次に、URL に移動し、このデータが存在することを確認します。

page.route("*/**/api/v1/fruits", route -> {
Response response = route.fetch();
byte[] json = response.body();
JsonObject parsed = new Gson().fromJson(new String(json), JsonObject.class);
parsed.add(new JsonObject().add("name", "Loquat").add("id", 100));
// Fulfill using the original response, while patching the response body
// with the given JSON object.
route.fulfill(new Route.FulfillOptions().setResponse(response).setBody(parsed.toString()));
});

// Go to the page
page.navigate("https://demo.playwright.dev/api-mocking");

// Assert that the Loquat fruit is visible
assertThat(page.getByText("Loquat", new Page.GetByTextOptions().setExact(true))).isVisible();

テストのトレースでは、API が呼び出され、レスポンスが変更されたことがわかります。trace of test showing api being called and fulfilled

レスポンスを調べると、新しいフルーツがリストに追加されたことがわかります。trace of test showing the mock response

高度なネットワーキングの詳細をご覧ください。

HAR ファイルを使用したモック

HAR ファイルは、ページがロードされたときに行われたすべてのネットワークリクエストの記録を含む HTTP Archive ファイルです。リクエストとレスポンスのヘッダー、Cookie、コンテンツ、タイミングなどに関する情報が含まれています。HAR ファイルを使用して、テストでネットワークリクエストをモックできます。次の手順が必要です。

  1. HAR ファイルを記録します。
  2. HAR ファイルをテストとともにコミットします。
  3. テストで保存された HAR ファイルを使用してリクエストをルーティングします。

HAR ファイルの記録

HAR ファイルを記録するには、Page.routeFromHAR() または BrowserContext.routeFromHAR() メソッドを使用します。このメソッドは、HAR ファイルへのパスとオプションのオプションオブジェクトを受け取ります。オプションオブジェクトには URL を含めることができ、指定されたグロブパターンに一致する URL を持つリクエストのみが HAR ファイルから提供されます。指定しない場合、すべてのリクエストは HAR ファイルから提供されます。

update オプションを true に設定すると、リクエストを HAR ファイルから提供する代わりに、実際のネットワーク情報で HAR ファイルが作成または更新されます。テストを作成して、実際のデータで HAR を設定する場合に使用します。

// Get the response from the HAR file
page.routeFromHAR(Path.of("./hars/fruit.har"), new RouteFromHAROptions()
.setUrl("*/**/api/v1/fruits")
.setUpdate(true)
);

// Go to the page
page.navigate("https://demo.playwright.dev/api-mocking");

// Assert that the fruit is visible
assertThat(page.getByText("Strawberry")).isVisible();

HAR ファイルの変更

HAR ファイルを記録したら、'hars' フォルダー内のハッシュ化された .txt ファイルを開き、JSON を編集して変更できます。このファイルは、ソース管理にコミットする必要があります。update: true でこのテストを実行すると、API からのリクエストで HAR ファイルが更新されます。

[
{
"name": "Playwright",
"id": 100
},
// ... other fruits
]

HAR からの再生

HAR ファイルを記録および変更してモックデータを作成したので、テストで一致するレスポンスを提供するために使用できます。これを行うには、update オプションをオフにするか、単に削除します。これにより、API にアクセスする代わりに、HAR ファイルに対してテストが実行されます。

// Replay API requests from HAR.
// Either use a matching response from the HAR,
// or abort the request if nothing matches.
page.routeFromHAR(Path.of("./hars/fruit.har"), new RouteFromHAROptions()
.setUrl("*/**/api/v1/fruits")
.setUpdate(false)
);

// Go to the page
page.navigate("https://demo.playwright.dev/api-mocking");

// Assert that the Playwright fruit is visible
assertThat(page.getByText("Playwright", new Page.GetByTextOptions()
.setExact(true))).isVisible();

テストのトレースでは、ルートが HAR ファイルから処理され、API が呼び出されなかったことがわかります。trace showing the HAR file being used

レスポンスを調べると、新しいフルーツが JSON に追加されていることがわかります。これは、hars フォルダー内のハッシュ化された .txt ファイルを手動で更新することで行われました。trace showing response from HAR file

HAR 再生は、URL と HTTP メソッドを厳密に照合します。POST リクエストの場合、POST ペイロードも厳密に照合します。複数の記録がリクエストに一致する場合、最も一致するヘッダーを持つものが選択されます。リダイレクトが発生するエントリは自動的に追跡されます。

記録時と同様に、指定された HAR ファイル名が .zip で終わる場合、それは HAR ファイルとネットワークペイロードが個別のエントリとして保存されたアーカイブと見なされます。このアーカイブを抽出して、ペイロードまたは HAR ログを手動で編集し、抽出された har ファイルを指すこともできます。すべてのペイロードは、ファイルシステム上の抽出された har ファイルからの相対パスで解決されます。

CLI を使用した HAR の記録

テストの HAR ファイルを記録するには、update オプションをお勧めします。ただし、Playwright CLI で HAR を記録することもできます。

Playwright CLI でブラウザーを開き、--save-har オプションを渡して HAR ファイルを生成します。オプションで、--save-har-glob を使用して、関心のあるリクエスト (API エンドポイントなど) のみを保存します。har ファイル名が .zip で終わる場合、成果物は個別のファイルとして書き込まれ、すべて単一の zip に圧縮されます。

# Save API requests from example.com as "example.har" archive.
mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI -D exec.args="open --save-har=example.har --save-har-glob='**/api/**' https://example.com"

高度なネットワーキングの詳細をご覧ください。

WebSocket のモック

次のコードは、WebSocket 接続をインターセプトし、サーバーに接続する代わりに、WebSocket 経由の通信全体をモックします。この例では、"request""response" で応答します。

page.routeWebSocket("wss://example.com/ws", ws -> {
ws.onMessage(frame -> {
if ("request".equals(frame.text()))
ws.send("response");
});
});

または、実際のサーバーに接続したいが、メッセージを途中でインターセプトして変更またはブロックしたい場合があります。ページからサーバーに送信されたメッセージの一部を変更し、残りを変更しないままにする例を次に示します。

page.routeWebSocket("wss://example.com/ws", ws -> {
WebSocketRoute server = ws.connectToServer();
ws.onMessage(frame -> {
if ("request".equals(frame.text()))
server.send("request2");
else
server.send(frame.text());
});
});

詳細については、WebSocketRoute を参照してください。