# 算出プロパティ
算出プロパティは単純なJavaScriptのオブジェクトなのでテストを書くのが簡単です。
算出プロパティのテストを書く2つの方法を紹介します。numbersの算出プロパティによって偶数か奇数のリストをレンダーする<NumberRenderer>コンポーネントを作ります。
# テストを書く
<NumberRenderer>はBooleanのevenプロップを受け取ります。evenはtrueの場合、2, 4, 6, 8を表示します。falseの場合、1, 3, 5, 7, 9を表示します。numbersのプロパティで算出します。
# 値をレンダーしてテストを書く
テストを書いてみましょう。
import { shallowMount } from "@vue/test-utils"
import NumberRenderer from "@/components/NumberRenderer.vue"
describe("NumberRenderer", () => {
it("偶数をレンダー", () => {
const wrapper = shallowMount(NumberRenderer, {
propsData: {
even: true
}
})
expect(wrapper.text()).toBe("2, 4, 6, 8")
})
})
実行する前に<NumberRenderer>を書いてみます。
<template>
<div>
</div>
</template>
<script>
export default {
name: "NumberRenderer",
props: {
even: {
type: Boolean,
required: true
}
}
}
</script>
開発しましょう。yarn test:unitを実行して、エラーメッセージによって進みます。
● NumberRenderer › 偶数をレンダー
expect(received).toBe(expected) // Object.is equality
Expected: "2, 4, 6, 8"
Received: ""
numbersの算出プロパティを書いてみます。
computed: {
numbers() {
const evens = []
for (let i = 1; i < 10; i++) {
if (i % 2 === 0) {
evens.push(i)
}
}
return evens
}
}
テンプレートを更新して新しく書いたプロパティを使います:
<template>
<div>
{{ numbers }}
</div>
</template>
yarn test:unitを実行すると:
FAIL tests/unit/NumberRenderer.spec.js
● NumberRenderer › 偶数をレンダー
expect(received).toBe(expected) // Object.is equality
Expected: "2, 4, 6, 8"
Received: "[
2,
4,
6,
8
]"
数は正しいですが、リストをいい感じにフォーマットしたいです。返す値を更新します:
return evens.join(", ")
yarn test:unitを実行したらパスです。
# callでテストを書く
even: falseの場合のテストを追加しましょう。今回はコンポーネントをレンダーせずに算出プロパティをテストする方法を紹介します。
先にテストを書きます:
it("奇数をレンダー", () => {
const localThis = { even: false }
expect(NumberRenderer.computed.numbers.call(localThis)).toBe("1, 3, 5, 7, 9")
})
コンポーネントをshallowMountでレンダーしてwrapper.text()の検証をする代わりに、callで別のthisを渡します。テストをパスしてから、callを使わないとどうなるかをみます。
上に書いてあるテストを実行する:
FAIL tests/unit/NumberRenderer.spec.js
● NumberRenderer › 奇数をレンダー
expect(received).toBe(expected) // Object.is equality
Expected: "1, 3, 5, 7, 9"
Received: "2, 4, 6, 8"
numbersを更新します:
numbers() {
const evens = []
const odds = []
for (let i = 1; i < 10; i++) {
if (i % 2 === 0) {
evens.push(i)
} else {
odds.push(i)
}
}
return this.even === true ? evens.join(", ") : odds.join(", ")
}
偶数と奇数の場合はパスです。callを使わないとどうなりますか?使わないように更新します:
it("奇数をレンダー", () => {
const localThis = { even: false }
expect(NumberRenderer.computed.numbers()).toBe("1, 3, 5, 7, 9")
})
このままでテストを実行すると失敗します。
FAIL tests/unit/NumberRenderer.spec.js
● NumberRenderer › 奇数をレンダー
expect(received).toBe(expected) // Object.is equality
Expected: "1, 3, 5, 7, 9"
Received: "2, 4, 6, 8"
vueはpropsをthisにバンドしてくれます。shallowMountなどでレンダーしないので、thisに何もバインドしません。numbersの中でconsole.log(this)をするとthisが見えます。thisはnumbersプロパティがあるcomputedオブジェクトとなります。
{ numbers: [Function: numbers] }
それでcallを使うと別のthis値を渡せます。上のテストでevenプロパティがあるthisオブジェクトを渡しました。
# callかshallowMount?
算出プロパティのテストを書くにはcallとshallowMountが両方とも便利なテクニックです。callが特に便利な場合は:
mountedなどの インスタンスライフサイクルフック の実行に時間がかかる場合、またライフサイクルフックを呼び出したくない場合です。コンポーネントをレンダーしないので、ライフサイクルフックも実行しません。thisを細かく設定したい場合
もちろんコンポーネントが正しくレンダーするテストも必要です。テストしたいことに合わせてもっとも適切なテクニックを選んで、エッジケースをちゃんとテストします。