🐡

Nuxtのcomponentsプロパティを使ったら単体テストでエラーになる

2 min read

Nuxt.js の components プロパティとは

Nuxt.js v2.13から導入された components プロパティは、コンポーネントのスキャンと自動インポートをしてくれます。

components プロパティ - NuxtJS

つまり、コンポーネントを使う時に import 文と components オプションを書く必要がなくなります。

nuxt.config.js
export default {
  components: true,
}
pages/index.vue
<template>
  <Hoge />
</template>

<script>
// 不要
// import hoge from '@/components/Hoge.vue'

export default {
  // 不要
  // components: {
  // 	Hoge,
  // },
}
</script>

公式ドキュメントによれば、これは nuxt/components によって実現されているようです。

この components プロパティですが、開発時はとても便利でした。
コンポーネントを作るたびに毎度毎度 import してコンポーネントを登録して使う日々から我々を開放してくれます。

また、コンポーネントの遅延読み込みなどもやってくれる優れものです。

単体テストをしてみる

さて、それではjest と vue test utils によるコンポーネントの単体テストをしてみましょう。

test/index.spec.js
import { shallowMount } from '@vue/test-utils'
import Hoge from '@/components/Hoge.vue'
import Index from '@/pages/index.vue'

describe('components property true', () => {
  test('exists components', () => {
    const wrapper = shallowMount(Index)
    const hogeWrapper = wrapper.findComponent(Hoge)
    expect(hogeWrapper.exists()).toBe(true)
  })
})

すると、テストが失敗しコンポーネント?そんなの知らないよ?とエラーが吐かれます。

● components property true › exists components

  expect(received).toBe(expected) // Object.is equality

  Expected: true
  Received: false

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

found in
---> <Anonymous>
	<Root>

考えればすぐわかることですが、開発サーバーで動かしているときは nuxt.config.js の components プロパティが読み込まれるため、自動でコンポーネントを import してくれます。

ただし、単体テストはコンポーネント単位で実施するため、当然 nuxt.config.jsに指定されている components プロパティなんぞ知りもしない、というわけです。

ちなみに、コンポーネントが見つからない場合、wrapper.findComponents() は以下のような ErrorWrapper を返すようです。

ErrorWrapper {
  selector: { render: [Function: render], staticRenderFns: [] }
}

解決策

コンポーネントはちゃんと import しましょう。
(もしテスト時にも自動 import する技があればぜひご連絡いただきたいです。)

おわりに

実装より先にテストから書いていればこのようなことも早期発見できるなぁと、テストの偉大さを感じております。

また、フレームワークのプロパティを使うときは、環境を考えて選択しなければならないなと思いました。
便利なプロパティも、動作する環境による影響を良く考えて付き合っていきたいですね。

Discussion

ログインするとコメントできます