LoginSignup
4
5

More than 5 years have passed since last update.

Vueの算出プロパティのテスト

Posted at

これはVue Testing Handbookからの記事です。元の記事はこちら。Vue Testing Handbookに貢献したい方はこちらを参考してください。この記事のソースコード(コンポーネント、テスト)もそちらにあります。


算出プロパティ

算出プロパティは単純なJavaScriptのオブジェクトなのでテストを書くのが簡単です。

算出プロパティのテストを書く2つの方法を紹介します。numbersの算出プロパティによって偶数か奇数のリストをレンダーする<NumberRenderer>コンポーネントを作ります。

テストを書く

<NumberRenderer>Booleanevenプロップを受け取ります。eventrueの場合、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"

vuepropsthisにバンドしてくれます。shallowMountなどでレンダーしないので、thisに何もバインドしません。numbersの中でconsole.log(this)をするとthisが見えます。thisnumbersプロパティがあるcomputedオブジェクトとなります。

{ numbers: [Function: numbers] }

それでcallを使うと別のthis値を渡せます。上のテストでevenポロパティがあるthisオブジェクトを渡しました。

callshallowMount?

算出プロパティのテストを書くにはcallshallowMountが両方とも便利なテクニックです。callが特に便利な場合は:

  • mounted などの インスタンスライフサイクルフック の実行に時間がかかる場合、またライフサイクルフックを呼び出したくない場合です。コンポーネントをレンダーしないので、ライフサイクルフックも実行しません。
  • thisを細かく設定したい場合

もちろんコンポーネントが正しくレンダーするテストも必要です。テストしたいことに合わせてもっとも適切なテクニックを選んで、エッジケースをちゃんとテストします。

4
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
5