😶‍🌫️

StorybookでServerComponentの処理をモックする

2025/02/12に公開

Storybookを使ってコンポーネントを管理する際に、ServerComponent内部で fetch やDBアクセスをしているコンポーネントがあった時に処理をモックする方法を紹介します。モックにせずともPresenterのような処理と表示を物理的にコンポーネントを分ける方法もありますが、Storybookのためだけに分離させるのは微妙なこともあるので今回はモックにします。

利用するのは storybook-addon-module-mock というアドオンです。これを使うと jest.mock のように柔軟なモックを作ることができます。

npm install -D storybook-addon-module-mock

利用パッケージとバージョン

  • Storybook : 8.5.4
  • storybook-addon-module-mock : 1.3.4
  • Next.js : 15.1.7

Storybookの設定

  • storybook-addon-module-mock アドオンの有効化
  • 今回はNext.jsを利用しているので @storybook/nextjs を指定
  • experimentalRSC でReact Server Componentのサポートを有効化
    • 有効にしないと async/await コンポーネントが動きません
.storybook/main.ts
import type { StorybookConfig } from "@storybook/nextjs";

const config: StorybookConfig = {
  stories: ["../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"],
  addons: [
    {
      name: "storybook-addon-module-mock",
      options: {},
    },
  ],
  framework: {
    name: "@storybook/nextjs",
    options: {},
  },
  staticDirs: ["../public"],
  features: {
    experimentalRSC: true,
  },
};
export default config;

StoryでMockの指定

対象コンポーネント

  • fetchData がデータフェッチをするバックエンド側の処理です
MyServerComponent.tsx
import { fetchData } from "@/stories/fetchData";

export async function MyServerComponent() {
  const data = await fetchData();
  return (
    <div>
      Server Component {data.firstName} {data.lastName}
    </div>
  );
}
fetchData.ts
export async function fetchData() {
  // 本来はDBリクエストや外部APIをfetchする
  return { firstName: "foo", lastName: "bar" };
}

StoryでMock

  • parameters.moduleMock でモックにしたい関数を指定します
  • mockImplementation で任意の値を返す処理に差し替えが可能です
MyServerComponent.stories.ts
import type { Meta, StoryObj } from "@storybook/react";

import * as mock from "@/stories/fetchData";
import { createMock } from "storybook-addon-module-mock";
import { MyServerComponent } from "./MyServerComponent";

const meta: Meta<typeof MyServerComponent> = {
  component: MyServerComponent,
  parameters: {
    moduleMock: {
      mock: () => {
        const fetchData = createMock(mock, "fetchData");
        fetchData.mockImplementation(async () => {
          return { firstName: "John", lastName: "Doe" };
        });
        return [fetchData];
      },
    },
  },
};
export default meta;

type Story = StoryObj<typeof meta>;

export const Primary: Story = {
  args: {},
};

以上でStorybookでデータフェッチなどを行うServer Componentの処理をモックできます。簡単ですね。

ムーザルちゃんねる

Discussion