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

モック API

はじめに

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

APIリクエストをモックする

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

test("mocks a fruit and doesn't call api", async ({ page }) => {
// Mock the api call before navigating
await page.route('*/**/api/v1/fruits', async route => {
const json = [{ name: 'Strawberry', id: 21 }];
await route.fulfill({ json });
});
// Go to the page
await page.goto('https://demo.playwright.dev/api-mocking');

// Assert that the Strawberry fruit is visible
await expect(page.getByText('Strawberry')).toBeVisible();
});

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

詳細については、高度なネットワークを参照してください。

API応答を変更する

場合によっては、APIリクエストを行う必要がありますが、再現可能なテストを可能にするために応答をパッチする必要がある場合があります。この場合、リクエストをモックする代わりに、リクエストを実行し、変更された応答でそれを満たすことができます。

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

test('gets the json from api and adds a new fruit', async ({ page }) => {
// Get the response and add to it
await page.route('*/**/api/v1/fruits', async route => {
const response = await route.fetch();
const json = await response.json();
json.push({ name: 'Loquat', id: 100 });
// Fulfill using the original response, while patching the response body
// with the given JSON object.
await route.fulfill({ response, json });
});

// Go to the page
await page.goto('https://demo.playwright.dev/api-mocking');

// Assert that the new fruit is visible
await expect(page.getByText('Loquat', { exact: true })).toBeVisible();
});

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

応答を検査すると、新しい果物がリストに追加されたことがわかります。trace of test showing the mock response

詳細については、高度なネットワークを参照してください。

HARファイルによるモック

HARファイルは、ページが読み込まれたときに作成されたすべてのネットワークリクエストの記録を含むHTTPアーカイブファイルです。リクエストと応答のヘッダー、Cookie、コンテンツ、タイミングなどに関する情報が含まれています。HARファイルを使用して、テストでネットワークリクエストをモックできます。次の手順を実行する必要があります。

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

HARファイルの記録

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

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

または、ブラウザコンテキストを作成するときに、browser.newContext()recordHarオプションを使用してHARファイルを記録することもできます。これにより、コンテキストが閉じられるまで、コンテキスト全体のすべてのネットワークトラフィックをキャプチャできます。

HARファイルの変更

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

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

HARからのリプレイ

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

test('gets the json from HAR and checks the new fruit has been added', async ({ page }) => {
// Replay API requests from HAR.
// Either use a matching response from the HAR,
// or abort the request if nothing matches.
await page.routeFromHAR('./hars/fruit.har', {
url: '*/**/api/v1/fruits',
update: false,
});

// Go to the page
await page.goto('https://demo.playwright.dev/api-mocking');

// Assert that the Playwright fruit is visible
await expect(page.getByText('Playwright', { exact: true })).toBeVisible();
});

テストのトレースでは、ルートが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.
npx playwright open --save-har=example.har --save-har-glob="**/api/**" https://example.com

詳細については、高度なネットワークを参照してください。

WebSocketをモックする

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

await page.routeWebSocket('wss://example.com/ws', ws => {
ws.onMessage(message => {
if (message === 'request')
ws.send('response');
});
});

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

await page.routeWebSocket('wss://example.com/ws', ws => {
const server = ws.connectToServer();
ws.onMessage(message => {
if (message === 'request')
server.send('request2');
else
server.send(message);
});
});

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