🪃
【Jest + Testing Library + MSW】再フェッチ挙動の再現
ちょっとしたことですが「どうやって実装すればいいんだっけ?」となったので
はじめに
何らかの処理を行った後にデータを再フェッチするページのコンポーネントがあるとして、そのコンポーネントをテストする際に、処理後の再フェッチの挙動を再現したい場合があります。
本記事では リクエスト回数に応じてAPIモックのレスポンスを変更し、再フェッチの挙動を再現する方法 を紹介します。
テストしたい内容
例えば何らかの設定を行うフォームがあったとして、初期状態では「未設定」のバッジが表示されているとします。
フォームを入力後送信ボタンがクリックされるとAPIリクエストが発生して入力内容が保存され、その後データが再フェッチされると「設定済」状態のデータが返され、そのレスポンスに応じてバッジの表示も変更される仕様です。
だいたいこんな実装のものがあるイメージです
type BadgeProps = {
status: ConfigStatus
};
export const Badge = ({ status }: BadgeProps) => (
<div>
<p>{status === 'configured' ? '設定済' : '未設定'}</p>
</div>
);
export const Page = () => {
const { data, refetch } = useFetchData();
const { mutate } = useMutateData();
const onSubmitHandler = async (formData) => {
try{
await mutate(format(formData));
await refetch();
} catch(err) {
// エラーハンドリング
}
}
return (
<div>
{data && <Badge status={data.status} />}
<form onSubmit={onSubmitHandler}>
{/* 以下入力フォームがある */}
</form>
</div>
);
};
テストの実装
テストで再現したい挙動は
- 初回リクエストでは設定が不完全な状態を返却する
- ボタン操作後の再フェッチでは、正しい設定情報を返却する
というものです。つまりデータフェッチが初回なのか2回目なのかを判定し、それに応じてレスポンスを変更できればいいということです。
リクエストの回数がカウントできればいいので、実装自体はかなりシンプルなものになりました。
実装例
// 各種importやモックサーバーのセットアップなどは省略
// ある程度簡略化しています
describe('Page Component', () => {
it('フォーム送信と再フェッチが正しく動作する', async () => {
let requestCount = 0;
server.use(
rest.get('/api/settings/1', (req, res, ctx) => {
requestCount += 1;
// 初回リクエストと再フェッチでレスポンスを変更
if (requestCount === 1) {
return res(
ctx.status(200),
ctx.json({
config_status: 'not_configured',
})
);
}
// 再フェッチ後のレスポンス
return res(
ctx.status(200),
ctx.json({
config_status: 'configured',
})
);
})
);
render(<Page />);
// 初回データ取得を待機
await waitFor(() => {
expect(/* 初回データ取得後に表示される何らかの要素 */).toBeInTheDocument();
});
// バッジが未設定
expect(await screen.findByText('未設定')).toBeInTheDocument();
const submitButton = screen.getByRole('button', { name: '送信' });
await userEvent.click(submitButton);
// 更新後の状態が反映されているか確認
expect(await screen.findByText('設定済')).toBeInTheDocument();
// APIリクエストが2度行われているか(=再フェッチの挙動が正しいか)確認
expect(requestCount)toBe(2);
});
});
Discussion