vue-test-utilsとJestの基本的な使い方、ユニットテストを作ろう！

この記事は私の今まで調べましたのことを共有したいです。
vue-test-utilsとJestの基本的な使い方です。
もし、他の方法・他の基本的なこと・質問・ご意見があったら、是非下にコメントしてください。
そして、間違えた日本語がある場合は、申し訳ございませんでした。

# バックグラウンド
この記事は、vue-test-utilsを使って、ユニットテストを書きたいのためです。
ユニットテストを書くがあまり人気じゃないですから、インターネットにチュートリアルもあまりないと思います。
普通の開発ことよりユニットテストは少ないと思います。
特にvue-test-utilsのチュートリアルには、探すことが本当に難しいと思います。
そして、半開発システムに、ユニットテストを書くは難しいです「これは私の経験からです」。だって、たくさんプラグインもう統合されています。例えば：Vue.jsのプロジェクトの場合なら、Vuex、vue-router、Vuetify、axios、などを使って、Vue.jsのsingle-page システムアプリケーションを作成する。
だから、この記事は書きたいです。
特に最初のステップからを始めての人に手伝いたいです。
これは今までvue-test-utilsについて、知っているのことが記事を書くです。

# 必要なもの
- Node.js v8.11.0+ (NPM v5.6.0+)
- vue-cli v3.0.0+
- vue.js v2.5.0+
- vue-router v3.0.0+
- vuex v3.0.0+
- vuetify v1.3.8

# 最初のこと
まずには、あなたはvue-cliを使って作成されたvueプロジェクトを持っていなければなりません。
じゃあ、簡単なVue.jsプロジェクトを作ろう！
ターミナルに書きます `vue create {PROJECT_NAME}`。
私の例では`vue create first-test-unit`

![Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293079/b60fddb1-587c-b622-8f26-7061250da8dd.png)
そのコマンドの後は、この絵のようなものを見えます。
`Manually select feature`を選びます

![Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293079/9ea984fd-d7bb-39cf-63db-d3f5f6778d00.png)
次に画像と同じものを選択してください。
>選ぶ方法は上下の矢印と選択するはスペースです。

![Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293079/7266bb39-c6ab-711b-f057-ccaf75bbb2c5.png)
次に画像と同じものを書くしてください。

![Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293079/742679f0-6c7d-010b-9b7d-f0a80c31c052.png)
次に`Jest`を選択してください

![Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293079/66c1917e-4b2c-0912-593d-f2dc61962a75.png)
次に画像と同じものを選択してください。

![Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293079/25455894-dc79-24a9-5506-2534263f378d.png)
次に画像と同じものを選択してください。

その後、インストールが完了するまで待ってください。
>インストールする別の方法はvue guiを使うことです。
>vue guiを使うのことはこちらです：https://qiita.com/Hendiche/items/6ddec49e03ea9c7c17b8

# 基本的なこと
vue.jsプロジェクトをインストールした後、IDEでプロジェクトを開いて、そして "tests"フォルダーに行ってください。
## 1) ファイル構造
推奨されるファイル構造はtests -> unitの中ではなく、コンポーネントの中に`__tests__`という名前のフォルダを作ることです。
![Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293079/4032c30d-8616-0fda-8941-c097f96f5346.png)

## 2) vue-router
ドキュメントから、global `vue-router`を使用するのではなく、`@vue/test-utils`の`localVue`を使用するように指示してください。
![Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293079/d47a9d05-c346-a70d-0580-286db602cc77.png)
![Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293079/e8e7e66e-10ef-a2fe-9072-6163987c31b1.png)


## 3) vuex
ドキュメントから、global `vuex`を使用するのではなく、`@vue/test-utils`の`localVue`を使用するように指示してください。
![Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293079/c8cd375c-b8cd-c947-5b73-d0e41ef410ca.png)
![Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293079/2e691d62-94ea-9d79-283d-f37046576b39.png)


## 4) vuetify
UIの設計に "vuetify"を使用する場合、テストのために "unknown custom element: ... - did you register the component correctly?"というエラーを防ぐためにvue-test-utilsに接続する必要があります。
![Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293079/7ea17b18-b97b-a4af-e890-e94354f5e7ba.png)
![Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293079/1d80a266-1a59-2768-b81e-b193aacc789c.png)

## 5) asynchronous Vue コンポーネント
asynchronouslyレンダリングコンポーネントのときに設定を設定するために使用します。
![Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293079/c97f0e4c-96c9-289a-4f9f-0662440465bc.png)

![Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293079/6f5c3fdc-a798-11b6-2b79-83a6ddb6860d.png)

## 6) PropsData
コンポーネントのpropsデータをmockするために使用される「propsData」。
![Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293079/3f11e43e-713a-cf70-7fd2-bab0f37f8884.png)
![Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293079/c45f527c-3a1a-dc99-d6ac-cc58632851c1.png)
![Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293079/374a8215-bc96-4716-f4c3-17798a1d5773.png)

## 7) ナビゲートルータ
このナビゲートルータではもっと複雑です。
ユニットテストのコードで、セットアップのために「vue-router②」と「vuetify④」を組み合わせ、`router` mocksを追加して、 `mount`で`wrapper`の方法を変更しなければいけません。
![Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293079/3f11e43e-713a-cf70-7fd2-bab0f37f8884.png)
![Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293079/2526aec5-4404-3e46-e218-434f4a33516d.png)
![Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293079/306658e2-62d1-e4ea-6300-136c736b4e44.png)

## 8) beforeAll() or beforeEach()
テストケースがたくさんある場合は、このコードを見てください。
長いコードたくさん二重化のコードがありますよね～

```javascript
import { shallowMount, mount, createLocalVue } from '@vue/test-utils';
import Router from 'vue-router';
import Vuex from 'vuex';
import Vue from 'vue';
import Vuetify from 'vuetify';

import AppExample from '../AppExample.vue'

Vue.use(Vuetify);
const localVue = createLocalVue();
localVue.use(Router);
localVue.use(Vuex);

describe('AppExample.vue', () => {
  test('connecting vue-router for testing', () => {
  	const wrapper = shallowMount(AppExample, {
  		localVue
  	});

  	expect(true).toBe(true);
  });

  test('connecting vuex for testing', () => {
  	const wrapper = shallowMount(AppExample, {
  		store: new Vuex.Store(),
  		localVue
  	});

  	expect(true).toBe(true);
  });

  test('using vuetify for testing', () => {
  	const wrapper = shallowMount(AppExample);

  	expect(true).toBe(true);
  });

  test('set "sync" for asynchronously render Vue component', () => {
  	const wrapper = shallowMount(AppExample, {
  		sync: false
  	});

  	expect(true).toBe(true);
  });

  test('set propsData', () => {
  	const propsData = {
  		btnRouteName: "navigate"
  	};

  	const wrapper = shallowMount(AppExample, {
  		propsData
  	});

  	expect(wrapper.find('#btnnavigate').exists()).toBe(true);
  });

  test('click navigation button to call router', async () => {
  	const propsData = {
  		btnRouteName: "boilerplateExample2",
  	};
  	const wrapper = mount(AppExample, {
  		localVue,
  		propsData,
  		router: new Router(),
  		sync: false,
  	});
  	const spy = jest.fn();
  	wrapper.vm.$router.push = spy;
  	wrapper.find('#btnboilerplateExample2').trigger('click');

  	await wrapper.vm.$nextTick();

  	expect(spy).toHaveBeenCalledWith({ name: 'boilerplateExample2' });
  });

})
```

と魔法を使って、、、、、、:smiling_imp:
pooooffffff........:robot:

```javascript
import { shallowMount, mount, createLocalVue } from '@vue/test-utils';
import Router from 'vue-router';
import Vuex from 'vuex';
import Vue from 'vue';
import Vuetify from 'vuetify';

import AppExample from '../AppExample.vue'

Vue.use(Vuetify);
const localVue = createLocalVue();
localVue.use(Router);
localVue.use(Vuex);

describe('AppExample.vue', () => {
	let wrapper;

	beforeAll(() => {
		const propsData = {
			btnRouteName: "boilerplateExample2",
		};

		wrapper = mount(AppExample, {
			store: new Vuex.Store(),
			localVue,
			sync: false,
			router: new Router(),
			propsData,
		});
	});

  test('connecting vue-router for testing', () => {
  	expect(true).toBe(true);
  });

  test('connecting vuex for testing', () => {
  	expect(true).toBe(true);
  });

  test('using vuetify for testing', () => {
  	expect(true).toBe(true);
  });

  test('set "sync" for asynchronously render Vue component', () => {
  	expect(true).toBe(true);
  });

  test('set propsData', () => {
  	expect(wrapper.find('#btnboilerplateExample2').exists()).toBe(true);
  });

  test('click navigation button to call router', async () => {
  	const spy = jest.fn();
  	wrapper.vm.$router.push = spy;
  	wrapper.find('#btnboilerplateExample2').trigger('click');

  	await wrapper.vm.$nextTick();

  	expect(spy).toHaveBeenCalledWith({ name: 'boilerplateExample2' });
  });

})

```
![Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293079/92ca8096-20c8-08c2-f713-437ea2904d80.png)

# エンディング
では、これはvue-test-utilsで単体テストを作成する基本的な使い方のいくつかです。
このいくつかの点では、すでにvue-test-utilsの基本的な使い方テストを作成することができます。

# ドキュメントリンク
- [Vue Test Utils](https://vue-test-utils.vuejs.org/)
- [Jest](https://jestjs.io/docs/en/getting-started.html)