Jest と Vue Test Utils による Vue コンポーネントのテスト
Vue CLI で作成した TypeScript 用の Vue プロジェクトに対して、Jest と Vue Test Utils(@vue/test-utils) を追加導入し、Vue コンポーネントのテスト(TypeScript で実装)を実施するようにしてみました。
今回は、Vue CLI の vue create
時に、Manually select features
を選択して、Choose Vue version
と TypeScript
にだけチェックを付け、Vue.js 2.x と 3.x のプロジェクトをそれぞれ作成して実施しています。
今回のソースは http://github.com/fits/try_samples/tree/master/blog/20210621/
(a) Vue.js 2.x の場合
まずは、Vue.js 2.x のプロジェクトで実施してみます。
- Vue.js 2.6.14
a-1. テストモジュールの導入
Jest と Vue Test Utils に必要なモジュールをインストールして設定します。
jest のインストールと設定
jest
と ts-jest
(テストコードを TypeScript で実装するため)、vue-jest
(テストコードで Vue コンポーネントを扱うため)をインストールします。
> npm i -D jest ts-jest vue-jest
ts-jest と vue-jest を適用するように Jest を設定し、jsdom を適用してテストを実施するよう testEnvironment
に jsdom
を設定しておきます。
jest.config.js 設定例
module.exports = { testEnvironment: 'jsdom', preset: 'ts-jest', transform: { '.*\\.(vue)$': 'vue-jest' } }
Vue Test Utils のインストール
@vue/test-utils
をインストールします。
> npm i -D @vue/test-utils
@types/jest のインストールと設定
ついでに、VS Code で jest の関数を使ってもエラー表示にならないようにするための措置を行っておきます。
まずは、jest の型定義をインストールします。
> npm i -D @types/jest
tsconfig.json の types
に jest
を追加します。
tsconfig.json 設定例
{ ・・・ "types": [ ・・・ "jest" ], ・・・ }
a-2. コンポーネントの実装
テスト対象のコンポーネントを実装します。
src/components/Counter.vue
<template> <div> <p> <button @click="countUp">count up</button> </p> <p> counter: {{ count }} </p> </div> </template> <script lang="ts"> import Vue from 'vue' export default Vue.extend({ data() { return { count: 0 } }, methods: { countUp() { this.count++ } } }) </script>
a-3. テストの実装と実施
テストコードを実装し、テストしてみます。
TypeScript で実装する場合、型の都合上 counter.vm.count
とする事はできなかったので、とりあえずは counter.vm.$data.count
としています。
(counter.vm as any).count
とする事も可能ですが、正直どちらも微妙な気がします。
tests/Counter.test.vue
import { mount } from '@vue/test-utils' import Counter from '../src/components/Counter.vue' test('count up', async () => { const counter = mount(Counter) expect(counter.vm.$data.count).toBe(0) // 以下でも可 // expect((counter.vm as any).count).toBe(0) await counter.get('button').trigger('click') expect(counter.vm.$data.count).toBe(1) })
jest コマンドでテストを実施します。
テスト実行
> npx jest PASS tests/Counter.test.ts (5.907 s) ・・・ Test Suites: 1 passed, 1 total Tests: 1 passed, 1 total Snapshots: 0 total Time: 7.434 s Ran all test suites.
(b) Vue.js 3.x の場合
次は、Vue.js 3.x のプロジェクトで実施してみます。
- Vue.js 3.1.1
b-1. テストモジュールの導入
基本的には 2.x と同じですが、インストールするモジュールのバージョンが多少異なります。
jest のインストールと設定
現時点で、Vue.s 3.x に対応した vue-jest
をインストールするにはバージョンに next
を指定する必要がありました。
また、(現時点で)インストールされる vue-jest 5.0.0-alpha.10 は、jest のバージョン 27
には対応しておらず、jest と ts-jest はバージョン 26
をインストールする必要がありました。
> npm i -D jest@26 ts-jest@26 vue-jest@next
Jest の設定は 2.x と同じですが、こちらは 2.x とは違って testEnvironment
を設定しなくても特に支障は無さそうでした。
jest.config.js 設定例
module.exports = { testEnvironment: 'jsdom', preset: 'ts-jest', transform: { '.*\\.(vue)$': 'vue-jest' } }
Vue Test Utils のインストール
@vue/test-utils のバージョンも next
とする必要がありました。
> npm i -D @vue/test-utils@next
また、@types/jest は 2.x と同様に、必要に応じてインストールして設定しておきます。
b-2. コンポーネントの実装
テスト対象コンポーネントを実装します。
src/components/Counter.vue
<template> <div> <p> <button @click="countUp">count up</button> </p> <p> counter: {{ count }} </p> </div> </template> <script lang="ts"> import { defineComponent } from 'vue' export default defineComponent({ data() { return { count: 0 } }, methods: { countUp() { this.count++ } } }) </script>
上記を以下のように Composition API で実装しても、同じテストコードでテストできました。
src/components/Counter.vue(Composition API 版)
<template> <div> <p> <button @click="countUp">count up</button> </p> <p> counter: {{ count }} </p> </div> </template> <script lang="ts"> import { ref } from 'vue' export default { setup() { const count = ref(0) const countUp = () => count.value++ return { count, countUp } } } </script>
b-3. テストの実装と実施
こちらは 2.x とは違って、counter.vm.count
とする事ができました。
tests/Counter.test.vue
import { mount } from '@vue/test-utils' import Counter from '../src/components/Counter.vue' test('count up', async () => { const counter = mount(Counter) expect(counter.vm.count).toBe(0) await counter.get('button').trigger('click') expect(counter.vm.count).toBe(1) })
jest コマンドでテストを実施します。
テスト実行
> npx jest PASS tests/Counter.test.ts ・・・ Test Suites: 1 passed, 1 total Tests: 1 passed, 1 total Snapshots: 0 total Time: 3.78 s, estimated 4 s Ran all test suites.