JavaScript
vue.js
vue-test-utils

Vueコンポーネントが発生したイベントのテスト

Vueコンポーネントが発生したイベントのテスト

アプリケーションが大きくなれば大きくなるほど、コンポーネントも増えていきます。親と子のコンポーネントをデータを共通するとき、子のコンポーネントがイベントを発火させて、親は反応します。

vue-test-utilswrapperAPIのemittedメソッドで発火したイベントを簡単に検証できます。ドキュメンテーションはこちらです。


これは最近作り始めたVueテストハンドブックからの記事です。貢献したい方はどうぞ。

このページのテストのソースコードはこちらにあります。


コンポーネントとテストを書く

簡単なコンポーネントを書きながら学びましょう。<Emitter>というコンポーネントを作って、このコードを書きます。

<template>
  <div>
  </div>
</template>

<script>
  export default {
    name: "Emitter",

    methods: { 
      emitEvent() {
        this.$emit("myEvent", "name", "password")
      }
    }
  }
</script>

<style scoped>
</style>

そしてemitEventを呼び出すメソッドがあるテストを書きます。

import Emitter from "@/components/Emitter.vue"
import { shallowMount } from "@vue/test-utils"

describe("Emitter", () => {
  it("2つの引数があるイベントを発火する", () => {
    const wrapper = shallowMount(Emitter)

    wrapper.vm.emitEvent()

    console.log(wrapper.emitted())
  })
})

vue-test-utilsemitted APIでコンポーネントが発生したイベントが見えます。

yarn test:unitでテストを実行してみます。

PASS  tests/unit/Emitter.spec.js
Emitter
  ✓ 2つの引数があるイベントを発火する (31ms)

console.log tests/unit/Emitter.spec.js:10
  { myEvent: [ [ 'name', 'password' ] ] }

emittedのシンタックス

emittedはオブジェクトを返します。発生したイベントはプロパティになります。emitted().[event]で検証できます:

emitted().myEvent //=>  [ [ 'name', 'password' ] ]

emitEventを二回呼び出してみます。

it("2つの引数があるイベントを発火する", () => {
  const wrapper = shallowMount(Emitter)

  wrapper.vm.emitEvent()
  wrapper.vm.emitEvent()

  console.log(wrapper.emitted().myEvent)
})

yarn test:unitで実行してみると:

console.log tests/unit/Emitter.spec.js:11
  [ [ 'name', 'password' ], [ 'name', 'password' ] ]

emitted().emitEventは配列を返します。最初に発生したイベントはemitted().emitEvent[0]でアクセスできます。イベントの引数をemitted().emitEvent[0][0]などでアクセスできます。

テストでイベントが発生したかを検証してみます。

it("2つの引数があるイベントを発火する", () => {
  const wrapper = shallowMount(Emitter)

  wrapper.vm.emitEvent()

  expect(wrapper.emitted().myEvent[0]).toEqual(["name", "password"])
})

テストはパスします。

コンポーネントをマウントせずにイベントのテスト

コンポーネントをレンダーせずにイベントが発生したかをcallで検証できます。新しいテストを書きます。

it("コンポーネントをレンダーせずにイベントを検証する", () => {
  const events = {}
  const $emit = (event, ...args) => { events[event] = [...args] }

  Emitter.methods.emitEvent.call({ $emit })

  expect(events.myEvent).toEqual(["name", "password"])
})

$emitはただのJavaScriptのオブジェクトなので、$emitをモックして、callemitEventthisにつけます。createdmountedのライフサイクルフックに重い処理をする場合、callで呼び出したらコンポーネントはマウントしないので、ライフサイクルメソッドも呼び出しません。thisを細かく指定したい時にも便利です。

まとめ

  • vue-test-utilsemittedAPIでコンポーネントによって発生したイベントを検証できます。
  • emittedは関数です。呼び出したイベントはemittedが返すオブジェクトのプロパティになります。
  • そのプロパティは配列です。イベントが数回発生したら、[0][1]などでアクセスできます。
  • 発生したイベントの引数も配列になります。[0][1]でアクセスします。
  • $emitをモックしてcallで呼び出して、レンダーせずに検証できます。

このページのテストのソースコードはこちらにあります。