【Nuxt.js】@nuxtjs/composition-apiでuseContextから読み込んだaxiosをテストする

@nuxtjs/composition-apiを使ったプロジェクトで、$axios.postを発火するメソッドをテストをする際にかなり詰まったので記事にします。

検証環境
  • nuxt: 2.15.3
  • @nuxtjs/composition-api: 0.22.3
  • @nuxt/typescript-build: 2.1.0
  • jest: 26.6.3
  • @vue/test-utils: 1.1.3


ざっくり結論

Vue Test Utilsのマウンティングオプションで$nuxtcontextをモックする



$axiosが読み込まれない問題

useContext()から$axiosを読み込み、postgetを叩く実装をしている場合、テストで$axiosを読み込んでくれないことがあります。

<template>
  <div>
    <h1>axios</h1>
    <el-button round @click="axiosMethod">button</el-button>
  </div>
</template>

<script lang="ts">
import { defineComponent, useContext } from '@nuxtjs/composition-api'

export default defineComponent({
  setup() {
    const { $axios } = useContext()

    const axiosMethod = async () => {
      await $axios.post('api/hoge')
    }

    return {
      axiosMethod,
    }
  },
})
</script>

<style></style>
import { shallowMount, createLocalVue } from '@vue/test-utils'
import Element from 'element-ui'
import AxiosPage from '@/pages/form/axios.vue'

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

const mockAxios = {
  post: jest.fn(),
}

describe('Axios', () => {
  let wrapper

  beforeEach(() => {
    wrapper = shallowMount(AxiosPage, {
      localVue,
      mocks: {
        $axios: mockAxios,
      },
    })
  })

  describe('単体テスト', () => {
    describe('axiosMethod', () => {
      it('POST api/hogeが叩かれる', async () => {
        await wrapper.vm.axiosMethod()
        expect(mockAxios.post).toHaveBeenCalledTimes(1)
      })
    })
  })
})
  ● Axios › 単体テスト › axiosMethod › POST api/hogeが叩かれる

    TypeError: Cannot read property 'post' of undefined

      14 |
      15 |     const axiosMethod = async () => {
    > 16 |       await $axios.post('api/hoge')
         | ^
      17 |     }
      18 |
      19 |     return {

Option apiでは上記のテストで通ります(多分)。

composition apiにおけるjest

jestはNuxtのcontextを知らないので、contextから読み込む$axios$nuxtとしてmockしてあげる必要があるようです。

// ・・・

const mockAxios = {
  post: jest.fn(),
}

describe('Axios', () => {
  let wrapper

  beforeEach(() => {
    wrapper = shallowMount(AxiosPage, {
      localVue,
      mocks: {
        $nuxt: {  // 追加
          context: {  // 追加
            $axios: mockAxios,
          },
        },
      },
    })
  })
  // ・・・

})
$ yarn test
yarn run v1.22.10

$ jest --config jest.config.js
 PASS  test/axios.spec.js
  Axios
    単体テスト
      axiosMethod
        ✓ POST api/hogeが叩かれる (53 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        4.24 s
Ran all test suites.

✨  Done in 5.19s.

通りました!

ついでにcontext.rootについて

$axios(などnuxtのcontextに依存するもの)を利用したい場合、以下のようにsetupメソッドの第二引数からcontextを受け取り、rootから読み込むことが推奨されている文献をよく見かけます。

<script lang="ts">
import { defineComponent } from '@nuxtjs/composition-api'

export default defineComponent({
  setup(_, context) {
    const axiosMethod = async () => {
      await context.root.$axios.post('api/hoge')
    }

    return {
      axiosMethod,
    }
  },
})
</script>

rootからの読み込みはVue3で非推奨の書き方のようです。

非推奨メッセージ(エディタ)

@nuxtjs/composition-apiでは基本的にuseContextから使うので大丈夫だと思いますが、composition api導入当初は戸惑いポイントだったので、気をつけたいと思います。

参考

fix: jest test reports error when encountering `useContext` · Issue #248 · nuxt-community/composition-api · GitHub