# 算出プロパティ
算出プロパティは単純な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
を細かく設定したい場合
もちろんコンポーネントが正しくレンダーするテストも必要です。テストしたいことに合わせてもっとも適切なテクニックを選んで、エッジケースをちゃんとテストします。