項目 | クラスコンポーネント時代 | Composition API移行後 |
---|---|---|
モック対象 | modules, state, getters, actions を定義してVuex.Storeを作る | 同じくmodules, state, getters, actionsをVuex.Storeで作成 |
useStoreの有無 | 使わない(vuex-classでデコレート) | 使わない(setup関数内で手動importか、別フックから取得) |
storeの参照方法 | @State @Getter で自動バインド |
setup関数でcomputed等に手動バインド |
テストからの操作方法 | (wrapper.vm as any).〇〇 でアクセス |
wrapper.vm.〇〇 でアクセス可能 |
✅ 結論として、
モックの作り方自体は「今まで通り」でOKですが、
テスト対象側の読み方・触り方だけがシンプルに変わる、というイメージです。
// ファイル名: storeMock.ts
import Vuex from 'vuex';
// Vuexモックストア作成関数
export function createStoreMock() {
return 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(), // Actionのモック
},
},
},
});
}
// ファイル名: 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';
import { createStoreMock } from '@/tests/storeMock';
const localVue = createLocalVue();
localVue.use(Vuex);
describe('ParentComponent.vue (Composition API版)', () => {
let store: any;
beforeEach(() => {
store = createStoreMock();
});
it('スナップショットと一致すること', () => {
const wrapper = shallowMount(ParentComponent, {
localVue,
store,
stubs: {
ChildComponent,
},
});
expect(wrapper.element).toMatchSnapshot();
});
it('ボタンをクリックするとupdateTextが呼ばれること', async () => {
const wrapper = shallowMount(ParentComponent, {
localVue,
store,
stubs: {
ChildComponent,
},
});
// childValueを直接変更
wrapper.vm.childValue = '新しいテキスト';
// ボタンクリック
const button = wrapper.find('button');
await button.trigger('click');
// Vuexアクションが呼ばれたか検証
expect(store._modulesNamespaceMap['sampleModule/'].context.dispatch).toHaveBeenCalledWith('updateText', '新しいテキスト');
});
});