Skip to content

Instantly share code, notes, and snippets.

@yukikim
Last active August 21, 2025 21:10
Show Gist options
  • Save yukikim/4eefcb68e314cc74ebd688b7a4201da7 to your computer and use it in GitHub Desktop.
Save yukikim/4eefcb68e314cc74ebd688b7a4201da7 to your computer and use it in GitHub Desktop.
Nuxtjsでjest

なるほど 👍 Nuxt.js + TanStack Query + Jest で「APIを呼び出して取得したデータを表示するコンポーネント」をテストするサンプルを紹介します。 ここでは 疑似 API をモック化 し、useQuery が返すデータをテスト対象のコンポーネントに流す例を示します。


前提

  • Nuxt 3
  • @tanstack/vue-query 使用
  • Jest + @vue/test-utils 使用

例: API + コンポーネント

composables/useApi.ts

export async function fetchUsers(): Promise<{ id: number; name: string }[]> {
  const res = await fetch("https://example.com/api/users");
  if (!res.ok) throw new Error("Failed to fetch");
  return res.json();
}

components/UserList.vue

<script setup lang="ts">
import { useQuery } from "@tanstack/vue-query";
import { fetchUsers } from "~/composables/useApi";

const { data, isLoading, error } = useQuery({
  queryKey: ["users"],
  queryFn: fetchUsers,
});
</script>

<template>
  <div>
    <div v-if="isLoading">Loading...</div>
    <div v-else-if="error">Error: {{ error.message }}</div>
    <ul v-else>
      <li v-for="user in data" :key="user.id">{{ user.name }}</li>
    </ul>
  </div>
</template>

単体テスト (Jest)

tests/UserList.spec.ts

import { mount } from "@vue/test-utils";
import { defineComponent } from "vue";
import { VueQueryPlugin, QueryClient, QueryClientProvider } from "@tanstack/vue-query";
import UserList from "~/components/UserList.vue";

// fetchUsers をモック化
jest.mock("~/composables/useApi", () => ({
  fetchUsers: jest.fn(),
}));
import { fetchUsers } from "~/composables/useApi";

// VueQuery 用のラッパー
function mountWithVueQuery(component: any) {
  const queryClient = new QueryClient();
  return mount(component, {
    global: {
      plugins: [
        [VueQueryPlugin, { queryClient }],
      ],
    },
  });
}

describe("UserList.vue", () => {
  it("APIデータを表示できる", async () => {
    (fetchUsers as jest.Mock).mockResolvedValue([
      { id: 1, name: "Alice" },
      { id: 2, name: "Bob" },
    ]);

    const wrapper = mountWithVueQuery(UserList);

    // データ取得完了を待つ
    await flushPromises();

    expect(wrapper.text()).toContain("Alice");
    expect(wrapper.text()).toContain("Bob");
  });

  it("エラー時の表示", async () => {
    (fetchUsers as jest.Mock).mockRejectedValue(new Error("API failed"));

    const wrapper = mountWithVueQuery(UserList);

    await flushPromises();

    expect(wrapper.text()).toContain("Error: API failed");
  });

  it("ローディング表示", async () => {
    (fetchUsers as jest.Mock).mockImplementation(
      () => new Promise(() => {}) // resolveしない
    );

    const wrapper = mountWithVueQuery(UserList);

    expect(wrapper.text()).toContain("Loading...");
  });
});

ポイント

  1. Nuxt でも jest で Vue コンポーネントをテストする場合@vue/test-utils を使う
  2. VueQuery の依存性注入VueQueryPluginglobal.plugins に渡す
  3. API は jest.mock でモック化
  4. 非同期処理の完了を待つawait flushPromises() を使う

👉 このサンプルを Nuxt プロジェクトに組み込めば、

  • API が成功するケース
  • 失敗するケース
  • ローディング中

の3パターンをテストできます。


ご希望に合わせて、このサンプルを Nuxt の pages/index.vue を対象にしたテスト例 に書き換えることもできますが、そちらにしますか?

いい質問です 👍 基本的な流れは Jest → Vitest に差し替え で動きますが、いくつかポイントがあります。


違いまとめ

  • jest.mockvi.mock
  • jest.fnvi.fn
  • 非同期処理待ち → flushPromises はそのまま使えます
  • 実行コマンドは vitest(Nuxt3 なら nuxi test でもOK)

サンプルコード(Vitest版)

tests/UserList.spec.ts

import { mount, flushPromises } from "@vue/test-utils";
import { describe, it, expect, vi } from "vitest";
import { VueQueryPlugin, QueryClient } from "@tanstack/vue-query";
import UserList from "~/components/UserList.vue";

// fetchUsers をモック化
vi.mock("~/composables/useApi", () => ({
  fetchUsers: vi.fn(),
}));
import { fetchUsers } from "~/composables/useApi";

// VueQuery 用のラッパー
function mountWithVueQuery(component: any) {
  const queryClient = new QueryClient();
  return mount(component, {
    global: {
      plugins: [[VueQueryPlugin, { queryClient }]],
    },
  });
}

describe("UserList.vue (vitest)", () => {
  it("APIデータを表示できる", async () => {
    (fetchUsers as unknown as ReturnType<typeof vi.fn>).mockResolvedValue([
      { id: 1, name: "Alice" },
      { id: 2, name: "Bob" },
    ]);

    const wrapper = mountWithVueQuery(UserList);
    await flushPromises();

    expect(wrapper.text()).toContain("Alice");
    expect(wrapper.text()).toContain("Bob");
  });

  it("エラー時の表示", async () => {
    (fetchUsers as unknown as ReturnType<typeof vi.fn>).mockRejectedValue(
      new Error("API failed")
    );

    const wrapper = mountWithVueQuery(UserList);
    await flushPromises();

    expect(wrapper.text()).toContain("Error: API failed");
  });

  it("ローディング表示", async () => {
    (fetchUsers as unknown as ReturnType<typeof vi.fn>).mockImplementation(
      () => new Promise(() => {}) // resolveしない
    );

    const wrapper = mountWithVueQuery(UserList);
    expect(wrapper.text()).toContain("Loading...");
  });
});

補足

  • vi.mock の場合は import の前にモック宣言してもOK ですが、上記のように vi.mockimport の順に書けば Jest と同じ流れで書けます。
  • Nuxt 3 + Vitest の場合、デフォルトで @vue/test-utils が動作するようになっているので、特別な設定は不要です。

👉 Jest 版からの変更点は jest → vi の置き換え だけで、テストの流れは全く同じです。

ご希望なら、このサンプルを Nuxt3 の nuxi test 環境nuxt.config.ts 設定込み)に合わせた完全セットアップ例 も提示できますが、そこまで要りますか?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment