👻

Nuxt.jsとJestで非同期通信の結果を表示するalertのテストをする

2021/01/23に公開

Nuxt.jsでコンポーネントの単体テストを作成していて、以下2つをテストをしたい。

  • axiosで処理を投げる
  • 上記のレスポンスから取得した内容をalertで表示する

環境

  • Vue.js 2.6.12
  • Nuxt.js 2.14.12
  • Jest 26.6.3
  • @nuxtjs/axios 5.12.5
  • @vue/test-utils 1.1.2
  • vue-jest 3.0.7

前提

テスト対象コンポーネント

仕様

ボタンを押すとAPI通信をして、レスポンスからnameを取得しalertで表示する
JSONPlaceholderを利用

想定レスポンス

  • エンドポイント : GET /users/1
{
   "id": 1,
  "name": "Leanne Graham",
  "username": "Bret",
  "email": "Sincere@april.biz",
  "address": {
    "street": "Kulas Light",
    "suite": "Apt. 556",
    "city": "Gwenborough",
    "zipcode": "92998-3874",
    "geo": {
      "lat": "-37.3159",
      "lng": "81.1496"
    }
  },
  "phone": "1-770-736-8031 x56442",
  "website": "hildegard.org",
  "company": {
    "name": "Romaguera-Crona",
    "catchPhrase": "Multi-layered client-server neural-net",
    "bs": "harness real-time e-markets"
  }
}

コンポーネント

GetUserButton.vue
<template>
  <button @click="getUser">ボタン</button>
</template>

<script lang="js">
   import Vue from 'vue'
   const url = 'https://jsonplaceholder.typicode.com/users/1';

   export default Vue.extend({
      name: 'DoSomethingButtuon',
      methods: {
         async getUser(){
            const user = await this.$axios.$get(url);
            alert(user.name);
         }
      }
   })
</script>

テストコード

テスト項目

  • 想定したAPIのエンドポイントにアクセスしていること
  • ボタンをクリックしたときに、APIから返ってきた結果をalertに表示できていること

テストコード全体

GetUserButton.spec.js
import GetUserButton from '@/components/GetUserButton.vue';
import { mount } from '@vue/test-utils';

let wrapper;
beforeAll(() => {
  wrapper = mount(GetUserButton, {
    // mocksプロパティにaxiosのモックを設定
    mocks: {
      $axios: {
        $get: jest.fn(() => Promise.resolve({ name: 'test user' }))
      }
    }
  })

  // window.alertをモックにする。Jestではモックにしないとエラーになる
  window.alert = jest.fn()
})

describe('GetUserButton', () => {
  // テストメソッドの第2引数にasyncをつける
  it('should access the appropriate endpoints', async () => {
    // 非同期処理なので、awaitをつける
    await wrapper.find('button').trigger('click');

    expect(wrapper.vm.$axios.$get).toHaveBeenCalledWith(
      'https://jsonplaceholder.typicode.com/users/1'
    )
  })

  it('should display alerts with user name', async () => {
    await wrapper.find('button').trigger('click');

    expect(window.alert).toHaveBeenCalledWith('test user');
  })
})

mocks プロパティに axios のモックを設定

通常実行時はNuxtがaxiosをいい感じにしてくれますが、Jestでは自分で設定する必要があります。
テストで共通に使うのでbeforeAllを使って、テスト対象のコンポーネントを準備しています。

GetUserButton.spec.js
let wrapper;
beforeAll(() => {
  wrapper = mount(GetUserButton, {
    // mocksプロパティにaxiosのモックを設定
    mocks: {
      $axios: {
        $get: jest.fn(() => Promise.resolve({ name: 'test user' }))
      }
    }
  })
})

window.alert にモックを設定

上記と同じように、window.alertもモックにしてあげます。

GetUserButton.spec.js
beforeAll(() => {
  ...
  // window.alertをモックにする。Jestではモックにしないとエラーになる
  window.alert = jest.fn()
})

trigger 部分は await をつける(合わせて it の第 2 引数に async)

テスト対象内では非同期通信をしているため、テストメソッドもそれに合わせてawait/asyncをつけます。

GetUserButton.spec.js
describe('GetUserButton', () => {
  // テストメソッドの第2引数にasyncをつける
  it('should access the appropriate endpoints', async () => {
    // 非同期処理なので、awaitをつける
    await wrapper.find('button').trigger('click');

    expect(wrapper.vm.$axios.$get).toHaveBeenCalledWith(
      'https://jsonplaceholder.typicode.com/users/1'
    )
  })
  ...
})

参考

Discussion