9.5 Before/Afterテストコード例


ここでは、実際に


■ ファイル構成(例)

src/
├── components/
│   ├── ParentComponent.vue
├── store/
│   ├── modules/
│   │   └── sampleModule.ts
├── tests/
│   ├── components/
│   │   └── ParentComponent.spec.ts


■ Before:クラスコンポーネント版テスト(変換前)

// ファイル名: tests/components/ParentComponent.spec.ts

import { shallowMount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
import ParentComponent from '@/components/ParentComponent.vue';
import ChildComponent from '@/components/ChildComponent.vue';

const localVue = createLocalVue();
localVue.use(Vuex);

describe('ParentComponent.vue', () => {
  let store: any;

  beforeEach(() => {
    store = new Vuex.Store({
      modules: {
        sampleModule: {
          namespaced: true,
          state: {
            text: 'テスト用テキスト',
            currentRoute: { name: 'home', path: '/' },
          },
          getters: {
            textLength: (state: any) => state.text.length,
            currentRouteName: (state: any) => state.currentRoute.name,
          },
          actions: {
            updateText: jest.fn(),
          },
        },
      },
    });
  });

  it('スナップショットと一致すること', () => {
    const wrapper = shallowMount(ParentComponent, {
      localVue,
      store,
      stubs: {
        ChildComponent,
      },
    });
    expect(wrapper.element).toMatchSnapshot();
  });

  it('ボタンをクリックするとupdateTextが呼ばれること', async () => {
    const wrapper = shallowMount(ParentComponent, {
      localVue,
      store,
      stubs: {
        ChildComponent,
      },
    });

    (wrapper.vm as any).childValue = '新しいテキスト';
    const button = wrapper.find('button');
    await button.trigger('click');

    expect(store._modulesNamespaceMap['sampleModule/'].context.dispatch).toHaveBeenCalledWith('updateText', '新しいテキスト');
  });
});


■ After:Composition API版テスト(変換後)

// ファイル名: tests/components/ParentComponent.spec.ts

import { shallowMount } from '@vue/test-utils';
import ParentComponent from '@/components/ParentComponent.vue';
import ChildComponent from '@/components/ChildComponent.vue';
import { useSampleModuleStoreMock } from '@/tests/mocks/useSampleModuleStoreMock';

// モックの作成
jest.mock('@/composables/useSampleModuleStore', () => ({
  useSampleModuleStore: () => useSampleModuleStoreMock(),
}));

describe('ParentComponent.vue', () => {
  it('スナップショットと一致すること', () => {
    const wrapper = shallowMount(ParentComponent, {
      global: {
        stubs: {
          ChildComponent,
        },
      },
    });
    expect(wrapper.element).toMatchSnapshot();
  });

  it('ボタンをクリックするとupdateTextが呼ばれること', async () => {
    const wrapper = shallowMount(ParentComponent, {
      global: {
        stubs: {
          ChildComponent,
        },
      },
    });

    const input = wrapper.find('input');
    await input.setValue('新しいテキスト');

    const button = wrapper.find('button');
    await button.trigger('click');

    expect(useSampleModuleStoreMock().updateText).toHaveBeenCalledWith('新しいテキスト');
  });
});


■ Before/After比較表

項目 Before(クラス版) After(Composition API版)
Vuexストアモック Vuex.Storeインスタンス作成 カスタムフック(useSampleModuleStore)をモック
mountオプション localVuestore渡す global.stubsだけ渡す
アクション検証 store._modulesNamespaceMap直接参照 フックのモック関数を参照
入力変更 vmのプロパティ直接変更 input.setValueを使う

■ まとめ

✅ Composition API移行後は、