hypermkt blog

平日はとあるホームページ作成サービス、週末はとあるレビューサイトの開発・運営。

Vue.js componentでvue-router,vue-resourceを利用したメソッドのUnitTestを書く方法

time 2016/11/26

Vue.js componentでvue-router,vue-resourceを利用したメソッドのUnitTestを書く方法

始めに

最近vue-resource・vue-routerを使ったSPAウェブサービスを開発・運用しており、ふとそろそろUnit Testを書いてみたいな〜と思い、ググってみたのですが思っていた以上に情報が見つからず・・・。ネット上で見つけたのは下記の3つのみ。

公式サイトを見ながら見よう見まねで書いてみたが、ハマりにハマってしまいもう無理だーとVue.jsコミュニティの方々に助けを求めました。皆さんから多数の提案を頂き、無事に解決しました。本当にありがとうございます!

今回はVue.jsコミュニティの方々に教えて頂いた、Vue.js componentのUnitTestを書く方法をまとめます。

前提

下記ライブラリを使用します。

  • Vue.js 2.0 + vue-resource + vue-router + vueify
  • karma
  • mocha
  • chai

テストケース 3パターン

  1. 普通のコンポーネントメソッド
  2. vue-routerのパラメーターを利用したメソッドのテスト
  3. vue-resourceでAPI呼び出しをしているメソッドのテスト

テストについて

  • Vue.jsの*.vueのコンポーネントを対象とし、methods内のメソッドをテストします。
  • 一部省略していますが、こちらにサンプルコードが置いてありますのでこちらをご覧ください。

パターン1:普通のコンポーネントメソッド

まずは外部ライブラリ、リソースを全く利用しない一番シンプルな例です。下記のようなaddという足し算メソッドがあったとします。

上記のメソッドのテストをする場合は以下のように記述します。ポイントは以下の通りです。
* テスト対象のコンポーネントをimportします。(読み込み時にファイルパスは適度の調整してください。)
* コンポーネント内のメソッドへはmethodsを通じて呼び出すことができます。これはVueの基本仕様通りメソッドはmethods内にあるからです。

また下記のようにすればメソッドの存在確認テストもできます。

ここまでは自分で出来ました。

パターン2:vue-routerのパラメーターを利用したメソッドのテスト

ここからは自分では解決できず、コミュニティの方の助言で解決しました。例えば下記のように vue-router のパラメーターを取得して文字列結合をするとします。

上記のメソッドのテストをする場合は以下のように記述します。ポイントは以下の通りです。

  • Vue.extendでサブクラスを作成し、テストケースの中でインスタンス化します
  • またインスタンス化時にbeforeCreateでルーティングのパラメーターを設定することが出来、ルーティングされた体でテストを書くことが出来るようになります。

パターン3:vue-resourceでAPI呼び出しをしているメソッドのテスト

今回一番悩んだのがこのテストケースでした。APIを利用してJSONで値を取得し、success時にデータオブジェクトのprofileを変更したい場合です。API呼び出しには vue-resourceのグローバル関数 Vue.http.get を利用していました。メソッドの返り値はPromiseとなり、非同期処理のテストってどうやるのか・・・。

ゴールのイメージとしては外部リソースであるAPIを実行しないようにモック化し、テスト対象のメソッド内で置き換えをすることです。

今回は Vue.http.getとグローバル関数を呼ぶので、下記のように算出プロパティを利用して$Vueからテスト対象オブジェク自身を取得できるように調整します。

次にテストケースです。ポイントは以下の通りです。

  • まずテストケースの引数にdoneを指定します。mochaの仕様でdone()の実行をもって非同期テストが終了したことをmochaに通知します。(通例的にdoneと命名されるそうです)
  • Vue.http.getでAPIを実際に呼び出さないようにモック化。getメソッドでPromiseの成功時にjson()メソッドがprofileのオブジェクトを返すように設定します。sinon等のモックライブラリを使わず、今回は仮の値を返す方式でも問題ありません。そしてテストケース2と同じ方式でコンポーネントをインスタンス化し、今回のテストケース用に設定した$Vueを通じて、Vueインスタンスのグローバル変数を上書きします。
  • 最後にテスト対象のメソッドを実行します。今回は非同期のテストにつき、そのままではPromiseの成功処理に入らないので、setTimeoutで擬似的に非同期にします。setTimeout内のdone()の実行をもって非同期テストが終了したことをmochaに通知され、モックで指定した通り Promise.resolveで成功処理に入りテストケースが通ります。

Special Thanks

今回はVue.jsコミュニティの下記の方々に1週間に渡って何度も助言頂きました。最後にはパッチまで準備して頂きありがとうございます!とても勉強になりました。

感想

普段からJavaScriptのテストコードを全く書いたことがなかったので、正直基本的な事から理解が出来ず苦労しました。ただVue.jsを通じてテストを書く機会が生まれて、この3パターンなら書けるようになりました。JavaScriptのテストコードコード楽しいですね〜。もっと書きたくなったぞー!


down

コメントする