テスト環境

  • @vue/cli-service@4.5.15
  • @vue/test-utils@1.3.0
  • @vue/vue2-jest@27.0.0
  • vue-jest@3.0.7
  • jest@27.5.1

テスト実行とエラー処理

コンポーネントテストを実行すると

npm run test:unit

下記のようなエラーが発生しました。

<router-view>は不明なカスタム要素であるため、コンポーネントの所在が不明ですと。コンポーネントを登録してくれ!といった内容です。

console.error
[Vue warn]: 
Unknown custom element: <router-view> - 
did you register the component correctly? For recursive components, 
make sure to provide the "name" option.
    
    found in
    
    ---> <Anonymous>
           <Root>

      at warn (node_modules/vue/dist/vue.runtime.common.dev.js:621:15)
      at createElm (node_modules/vue/dist/vue.runtime.common.dev.js:5962:11)
      at createChildren (node_modules/vue/dist/vue.runtime.common.dev.js:6077:9)
      at createElm (node_modules/vue/dist/vue.runtime.common.dev.js:5978:9)
      at VueComponent.patch [as __patch__] (node_modules/vue/dist/vue.runtime.common.dev.js:6499:7)
      at VueComponent.Vue._update (node_modules/vue/dist/vue.runtime.common.dev.js:3948:19)
      at VueComponent.updateComponent (node_modules/vue/dist/vue.runtime.common.dev.js:4069:10)
      at Watcher.get (node_modules/vue/dist/vue.runtime.common.dev.js:4481:25)
      at new Watcher (node_modules/vue/dist/vue.runtime.common.dev.js:4470:12)
      at mountComponent (node_modules/vue/dist/vue.runtime.common.dev.js:4076:3)
      at VueComponent.Object.<anonymous>.Vue.$mount (node_modules/vue/dist/vue.runtime.common.dev.js:8436:10)
      at init (node_modules/vue/dist/vue.runtime.common.dev.js:3131:13)
      at createComponent (node_modules/vue/dist/vue.runtime.common.dev.js:6002:9)

このエラーを解決するためには、マウントしているコンポーネントにvue-routerを使用できるようにする必要があります。

解決策は2つあります。

参照: Vue Router と一緒に使用する

解決策1: stubsオプションを使用する

import { shallowMount } from '@vue/test-utils'
import App from '@/App.vue'

describe('App.vue', () => {
  it('renders test', () => {
    const wrapper = shallowMount(App, {
      stubs: ['router-link', 'router-view']
    })
    expect(wrapper.isVueInstance).toBeTruthy()
  })
})

shallowMount()を使用すると、子コンポーネントをstubとして表示してくれるので子コンポーネントをレンダリングする必要がないとき(今回のようなApp.vueの描画テストのみの場合など)は、上記の方法でテストを書きます。

stubsオプションとして<router-view>や<router-link>を登録しておくことで、vue-routerのエラーが発生しなくなります。

解決策2: localVue による Vue Router のインストール

Vue.jsアプリケーションでは、vuexやvue-routerなどのグローバルプラグインを使用して開発を行うと思います。Vue Test Utilsでは、vuexやvue-routerなどのグローバルプラグイン、ミックスイン、コンポーネントをテストのエントリに設定することができます。

そのためには、createLocalVue()を使用します。

import { shallowMount, createLocalVue } from '@vue/test-utils'
import VueRouter from 'vue-router'

const localVue = createLocalVue()
localVue.use(VueRouter)

describe('App.vue', () => {
  it('renders test', () => {
    const wrapper = shallowMount(App, {
      localVue
    })
    expect(wrapper.isVueInstance).toBeTruthy()
  })
})

上記のように書くことでテスト内にvue-routerプラグインを使うことができ、<router-view>コンポーネントも認識されるようになります。

createLocalVue()

個人的な意見ですが、コンポーネントテストにおいて、vue-routerに依存する<router-view>の中身を検証する必要はないと考えています。

基本的にルーティングはアプリ全体の構造に関連しているので、結合テストやe2eテストで検証するのが一般的です。

なのでvue-routerに依存する<router-view>や<router-link>などのコンポーネントについては、stubsオプションやlocalVueを使ってモックするのが奨励されています。

グローバルプラグインとミックスインの適用

カテゴリー: Vue.js