PlaywrightでAPIをモックする 〜PokéAPIでヌオーさんを優勝させる〜
はじめに
バックエンドのAPIからデータを取得し、フロントエンドでVueやReactを使って表示する、というケースはよくあると思います。私の職場にはよくあります。
こういう場合のテストで、APIの値を好きにいじることができるとテストが捗ります。
そんな時のために、E2EテストのフレームワークであるPlaywrightはAPIモックを提供しています。
この記事は、PlaywrightでのAPIモックの方法を、ポケモンの情報が取れるPokéAPIをモックし、すべてをヌオーさんにしながら学んでいく、そんな記事です。
PokéAPI
ヌオーさん
サンプル用Reactアプリ
ほとんどテンプレートのままですが、PokéAPIを使ってポケモン情報を取得・表示するReactアプリを作りました。
npm init vite playwright_api_mock
Playwrightもセットアップします。
npm init playwright@latest
playwright.config.ts
でuse.screenshot
をtrueにしておきます。
App.tsx
は次のようにしました。
import { useEffect, useState } from 'react';
import axios from 'axios';
import { Pokemon } from './types';
function App() {
const [pokemon, setPokemon] = useState<Pokemon>();
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
axios.get('https://pokeapi.co/api/v2/pokemon/greninja')
.then(response => {
console.log(JSON.stringify(response.data));
setPokemon(response.data);
setLoading(false);
})
.catch(error => {
setError(error.message);
setLoading(false);
});
}, []);
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error}</div>;
return (
<div className="App">
<h1>ポケモン人気ランキング</h1>
<ul>
<li key={pokemon!.id}>
<h2>ポケモン人気ランキング第1位は{pokemon!.name}!</h2>
<img src={pokemon!.sprites.front_default} alt={pokemon!.name} />
</li>
</ul>
</div>
);
}
export default App;
Pokemon型は下記。
export interface Pokemon {
id: number;
name: string;
sprites: {
front_default: string;
}
}
ローカルでviteを立ち上げます。
npx vite --port=4000
http://localhost:4000/
にアクセスすると、https://pokeapi.co/api/v2/pokemon/greninja
から情報を取得、下記のように表示されます。greninjaはゲッコウガさんです。
このAPIをモックして、人気ポケモンをヌオーさんにしていきたいと思います。
PlaywrightのAPIモック
PlaywrightでのAPIモックの方法はドキュメントの下記で説明されています。
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();
});
このサンプルコードの要はここ。
await page.route('*/**/api/v1/fruits', async route => {
const json = [{ name: 'Strawberry', id: 21 }];
await route.fulfill({ json });
});
fulfill
によって、レスポンスを操作することができます。JSONデータを与えたいときは、引数にjson
オブジェクトを与えます。
サンプルアプリでモックしてみる
さっそくヌオーさんを人気ポケモンにしましょう。
tests/mockemon.spec.ts
を作成します。
ヌオーさんは英語でQuagsireといいます。沼(quagmire)の王さま(sire)です。
import { test, expect } from '@playwright/test';
import { Pokemon } from '../src/types';
test("ヌオーさんしか勝たん", async ({ page }) => {
const mockemon: Pokemon = {
id: 195,
name: 'quagsire',
sprites: {
front_default: 'https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/195.png'
}
}
await page.route('https://pokeapi.co/api/v2/pokemon/greninja', async route => {
await route.fulfill({ json: mockemon });
});
await page.goto('http://localhost:4000/');
await expect(page.getByText('quagsire')).toBeVisible();
});
ヌオーさんのモックデータ(mockemon
)を用意し、routeにfulfillでセットします。
これでテストを実行してみます。
npx playwright test mockemon.spec.ts
結果。ヌオーさんしか勝たん。
念のため、reportを開いてスクリーンショットも見てみます。
npx playwright show-report
ハロー、ヌオーさん!
App.tsx
のリクエストURLをgreninja
から、pikachu
に変えてみましょう。
+ axios.get('https://pokeapi.co/api/v2/pokemon/pikachu')
- axios.get('https://pokeapi.co/api/v2/pokemon/greninja')
localhost:4000はピカチュウのものとなりました。
テストを実行すると、failします。許せません。
ヌオーさんが電気ネズミ風情に負けないように、テストコードを修正します。
routeの引数には正規表現やglobパターンも使えますので、globで書き換えます。
+ await page.route('https://pokeapi.co/api/v2/pokemon/**', async route => {
- await page.route('https://pokeapi.co/api/v2/pokemon/grenja', async route => {
もう一度テストを実行します。
おわりに
というわけで、PokéAPIを例にplaywrightでのAPIモックを行いました。
PlaywrightでのAPIモックは簡単で、しかもVueやReactでのバックエンド通信をテストする際など、実務でもかなり便利です。
最後に本記事のまとめです。これだけ覚えればAPIモックができます。ぜひ覚えて帰ってください。
Discussion