Vuex を使っているコンポーネントをテストする場合、
mutation を直接使うなら state の変化を確認
action を dispatch
しているなら dispatch
が呼ばれるかを確認
→ 基本的には store
をモックして dispatch
を spy(監視) する。
<!-- src/components/Counter.vue -->
<template>
<div>
<p>Count: {{ count }}</p>
<!-- incrementAction を呼ぶ -->
<button @click="incrementAction">Increment</button>
</div>
</template>
<script lang="ts">
// クラスコンポーネント + Vuex
import { Vue, Component } from 'vue-property-decorator';
import { mapState, mapActions } from 'vuex';
@Component({
computed: {
...mapState(['count']), // Vuexのstateをcountとして使用
},
methods: {
...mapActions(['increment']), // Vuexのactionをincrementとして使用
},
})
export default class Counter extends Vue {
// TypeScript用に型を補足
get count(): number {
return (this as any).$store.state.count;
}
increment!: () => void;
// ボタンから呼ばれるメソッド
incrementAction(): void {
this.increment();
}
}
</script>
// tests/Counter.spec.ts
// CounterコンポーネントのVuex dispatchテスト
import { shallowMount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
import Counter from '@/components/Counter.vue';
const localVue = createLocalVue();
localVue.use(Vuex);
describe('Counter.vue', () => {
it('ボタンをクリックすると increment action が dispatch される', () => {
// dispatch をモック
const actions = { increment: jest.fn() };
// store の作成
const store = new Vuex.Store({
state: { count: 0 },
actions,
});
// shallowMount でstoreを渡す
const wrapper = shallowMount(Counter, {
store,
localVue,
});
// ボタンをクリック
wrapper.find('button').trigger('click');
// dispatch(increment)が呼ばれたか確認
expect(actions.increment).toHaveBeenCalled();
});
});
npx jest
PASS tests/Counter.spec.ts
Counter.vue
✓ ボタンをクリックすると increment action が dispatch される (5ms)