Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

これは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を細かく設定したい場合

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

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away