Vue-cli で作ったプロジェクトの Jest で開発用 API のテストをする

create-react-app や vue-cli で作成したアプリケーションは、簡単な設定で Jest によるテストを実行することができます。

今回は特に vue-cli でプロジェクトを作成して、Jest を使っていきます。

## vue-cli のインストール

まず vue-cli をグローバルにインストールします。ver3 を使用します。
https://cli.vuejs.org/guide/installation.html

```
npm install -g @vue/cli
vue --version # 3 と出れば OK
```

## GUI で Vue プロジェクトを作成する

![Screen Shot 2018-08-03 at 7.38.27 PM.png](https://qiita-image-store.s3.amazonaws.com/0/240885/5c23b42b-6059-0768-72d3-d345524c3a02.png)

https://cli.vuejs.org/guide/creating-a-project.html#using-the-gui

```
vue ui
```

create project -> preset -> Manual を選択 -> 以下くらいを選択する

- babel (必須)
- Linter/Formatter
- Using testing (必須)
- Use config files (強く推奨)

### Configuration
- ESLint + Prettier をおすすめ
- Unit testing solution は Jest で指定

で作成。

するとプロジェクトができます。

## デフォルトで用意されたテストを走らせてみる

```
npm run test:unit
```

すると以下のようにテストが実行されて通ったことがわかります。
.spec.js というファイル名のものがテストが書かれたファイルです。

![Screen Shot 2018-08-03 at 7.31.49 PM.png](https://qiita-image-store.s3.amazonaws.com/0/240885/cfd4fbdc-cda6-3e77-9729-aeef6f13ede2.png)

このテストに書かれたコードの概要は以下です。

```js:tests/unit/HelloWorld.spec.js
// vue のテスト用のモジュール
import { shallowMount } from "@vue/test-utils";

// 実際に書かれているコンポーネント
import HelloWorld from "@/components/HelloWorld.vue";

// テストを宣言していく
describe("HelloWorld.vue", () => {
  it("renders props.msg when passed", () => {
    const msg = "new message";
    
    // コンポーネントへ、テストを簡単にするためのラッピングをする
    const wrapper = shallowMount(HelloWorld, {
      // その際にコンポーネントに対して props を与える
      propsData: { msg }
    });

    // テスト結果がどうなるべきかを定義する
    // コンポーネント内のテキストが、msg = "new message" になっていることを期待
    expect(wrapper.text()).toMatch(msg);
  });
});
```

## テストを watch 状態で走らせる

やってみたらできただけで、マニュアルを見たわけではないのですが、以下のように package.json の script を変えれば、watch モードで Jest が走ります。変更があったテスト、テストに関係するファイルの変更を感知して、それだけを実行してくれます。

```json:package.json
{
  "script": { 
    "test:unit": "vue-cli-service test:unit --watch" 
  }
}
```

## axios でフェッチする API テストを書く

まずは axios をインストール

```
npm i axios
```

テストを書く。

ポイントは async ファンクションにすること。これによって axios 等プロミスベースで非同期通信するアプリケーションのテストも、簡単に書くことができる。

```js:Fetch.spec.js
import axios from "axios";

// async ファンクションにする
test("fetch test", async () => {
  const url = "https://api.myjson.com/bins/159wqn";

  // await でとってくるのを待つ
  const { data } = await axios.get(url);

  // これはしなくてもいいが中身をみとく
  console.log(data);

  // オブジェクトに member というプロパティがあることを期待
  // なければエラーが出る
  expect(data).toHaveProperty("member");
});
```

## Localstorage を使う

vue-cli で作ったアプリケーションの場合はうまくいくのですが、自分で webpack 等を設定した場合には、たいていの場合 localStorage が使えないと思います。自分はそうなりました。

そのためには jest-localstorage-mock を使います。

```
npm i -D jest-localstorage-mock
```

Jest の設定ファイルに以下を追加。

```js:jest.config.js
module.exports = {
 //
 setupFiles: ['<rootDir>/test/unit/setup', 'jest-localstorage-mock'],
 //
};

```

これで localStorage にもアクセスできます。

```js
import axios from "axios";

// async ファンクションにする
test("fetch test", async () => {
  const url = "https://api.myjson.com/bins/159wqn";

  // await でとってくるのを待つ
  const { data } = await axios.get(url);

  // これはしなくてもいいが中身をみとく
  console.log(data);

  // オブジェクトに member というプロパティがあることを期待
  // なければエラーが出る
  expect(data).toHaveProperty("member");

  // localStorage にもアクセスできる
  localStorage.setItem("item", "testItem");
  const storageItem = localStorage.getItem("item");
  console.log(storageItem);
});
```

あとは Jest のドキュメントで、expect().toBe 等々をチェックしてください。

## snapShot を取る

API で取得した値が常に一定かどうか、スナップショットを取ることで、違いが発生した時にエラーを吐くようにできます。
これでもしバックエンド側がフロント開発チームに告知なく API を変更したとしても、そのエラーに気づくことができます。

```js
import axios from "axios";

// async ファンクションにする
test("fetch test", async () => {
  const url = "https://api.myjson.com/bins/159wqn";

  // await でとってくるのを待つ
  const { data } = await axios.get(url);

  // これはしなくてもいいが中身をみとく
  console.log(data);

  // オブジェクトに member というプロパティがあることを期待
  // なければエラーが出る
  expect(data).toHaveProperty("member");

  localStorage.setItem("item", "testItem");
  const storageItem = localStorage.getItem("item");
  console.log(storageItem);
  
  // snapShot を取得する
  expect(data).toMatchInlineSnapshot();
});
```

## まとめ

Jest で非常に簡単にテストを実行することができました。

さらに Vuex やコンポーネントのテストの記事についても今後書きたいと思います。