きっかけ
コンポーネントのcomputedをテストする機会がありました。
しかしコンポーネント内の他の要素(ライフサイクルやストアなど)に依存してしまい、純粋にロジックのみをテストできないのだろうか...となっていました。
その際のメモです。
使用しているバージョン
- nuxt@2.15.8
- vue@2.6.14
- @vue/test-utils@1.3.0
方法
computedのテストには大きく分けて2つあります。
- mountやshallowMountを使う方法
- callを使う方法 <- 今回はこちら
テストしてみる
今回テストするコンポーネントはこちらです。
<template>
<div>
<!-- テンプレートの内容 -->
</div>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
data() {
return {
searchKeyword: '佐藤太郎',
}
},
computed: {
...mapGetters({
users: 'users/users',
}),
filteredUsers() {
return this.users.filter((u) => u.name === this.searchKeyword)
},
},
}
</script>
それではcallを使ったテストを書いてみましょう。
import VCard from '@/components/VCard.vue'
const dummyUsers = [
{ id: '1', name: 'hoge太郎' },
{ id: '2', name: 'fuga二郎' },
{ id: '3', name: 'piyo三郎' },
]
describe('VCard test', () => {
test('filteredUser computed', () => {
const localThis = {
users: dummyUsers,
searchKeyword: 'fuga二郎',
}
const expected = [dummyUsers[1]]
const received = VCard.computed.filteredUser.call(localThis)
expect(received).toEqual(expected)
})
})
VCard内でthis.users
やthis.searchKeyword
がlocalThisの内容に置き換えられます。
つまりmapGetters
やdata()
の中身を気にすることなく、ロジックがテストできます。
Vueテストハンドブックによると、以下の理由でthis
を置き換えることができるそうです。
shallowMountなどでレンダーしないので、thisに何もバインドしません。
便利!
これでライフサイクルを無視した純粋なcomputedのテストができました。
callかshallowMountどちらを使うか? (おまけ)
Vueテストハンドブックより引用です。
算出プロパティのテストを書くにはcallとshallowMountが両方とも便利なテクニックです。callが特に便利な場合は:
mounted
などの インスタンスライフサイクルフック の実行に時間がかかる場合、またライフサイクルフックを呼び出したくない場合です。コンポーネントをレンダーしないので、ライフサイクルフックも実行しません。this
を細かく設定したい場合
もちろんコンポーネントが正しくレンダーするテストも必要です。テストしたいことに合わせてもっとも適切なテクニックを選んで、エッジケースをちゃんとテストします。
うまく使い分けることが重要ですね。
Comments
Let's comment your feelings that are more than good