🎭

MSWで型安全にConnectの通信をモックする

2024/10/31に公開

結論

MSWを使用してConnectの通信をモックする場合、以下のようなヘルパー関数を用意することで型安全かつ簡潔にモックを記述できます:

import { ServiceType, MessageType } from "@bufbuild/protobuf";
import { RequestHandler, rest } from "msw";

export const mockConnectWeb =
 <T extends ServiceType>(service: T) =>
 <U extends keyof T["methods"]>(props: {
   method: U;
   data: T["methods"][U]["O"] extends MessageType<infer O> ? O : never;
 }): RequestHandler => {
   return rest.all(
     "*/" + service.typeName + "/" + service["methods"][props.method]?.name,
     (_req, res, ctx) => {
       return res(ctx.status(200), ctx.json(props.data));
     }
   );
 };

詳細な実装と使い方

モックヘルパー関数の特徴

このヘルパー関数には以下の特徴があります:

  1. 型安全性
  • ServiceTypeとそのメソッドの型を保証
  • レスポンスデータの型チェックを実現
  1. 使いやすさ
  • リクエストパスを自動的に構築
  • MSWのHandlerを適切に生成

実践的な使用例

Storybookなどでの使用例を見てみましょう:

export const Default: Story = {
 render: () => <EventManagerComponent />,
 parameters: {
   msw: {
     handlers: [
       mockConnectWeb(EventManagementService)({
         method: "getEventDetails",
         data: new EventDetailsResponse(),
       }),
       mockConnectWeb(EventManagementService)({
         method: "saveEventData",
         data: new SaveEventResponse(),
       }),
       // 他のエンドポイントのモック...
     ],
   },
 },
};

利点と注意点

利点

  1. 型の恩恵
  • 存在しないメソッド名の指定を防止
  • レスポンスの型不一致を防止
  • IDEの補完が効く
  1. 保守性
  • モック実装がシンプル
  • 再利用が容易
  • APIの変更が型システムで追跡可能

注意点

  1. エラーケースの考慮
  • 現状は200レスポンスのみ対応
  • エラーレスポンスが必要な場合は拡張が必要
  1. 実装の制限
  • 単純なレスポンス返却のみ対応
  • 複雑なモックが必要な場合は個別対応が必要

発展的な使い方

エラーケース対応

エラーケースにも対応したい場合は、以下のように拡張できます:

export const mockConnectWebWithError =
 <T extends ServiceType>(service: T) =>
 <U extends keyof T["methods"]>(props: {
   method: U;
   error?: { status: number; message: string };
   data?: T["methods"][U]["O"] extends MessageType<infer O> ? O : never;
 }): RequestHandler => {
   return rest.all(
     "*/" + service.typeName + "/" + service["methods"][props.method]?.name,
     (_req, res, ctx) => {
       if (props.error) {
         return res(
           ctx.status(props.error.status),
           ctx.json({ message: props.error.message })
         );
       }
       return res(ctx.status(200), ctx.json(props.data));
     }
   );
 };

おわりに

MSWとConnectを組み合わせることで、型安全かつメンテナンス性の高いAPIモックを実現できます。特にStorybookでのUI開発において有用です。必要に応じてエラーケースの対応など、機能を拡張していくことで、より実践的な使用が可能になります。

GitHubで編集を提案

Discussion