24
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Nuxt.jsの$router, $storeやcontextをjest+vue-test-utilsでモックする方法

Last updated at Posted at 2019-05-06

はじめに

nuxt.jsをJest+vue-test-utilsでテストする際に、nuxt.js特有のメソッド(this.$router.pushなど)やcontextをモックするのに大変苦労しました。
他の人が同じ苦労をせずにすんなりテストを書く手助けになればいいな〜と思います!

asyncDataやfetch以外でモックする方法

shallowMountやmountで用意されている、こちらのmocksというオプションを利用します。
https://vue-test-utils.vuejs.org/guides/#mocking-injections

$storeを使った例

以下は$storeのモックを作成した簡単な例です。

Vue

somePage.vue
<template>
  <div>
    <p v-if="isLoggedIn">
      ログインしています😊
    </p>
    <p v-if="!isLoggedIn">
      ログインしていません😢
    </p>
  </div>
</template>

<script>
import { mapGetters } from 'vuex'

export default {
  computed: {
    ...mapGetters(['isLoggedIn'])
  }
}
</script>

テスト

今回使っているのはstoregetters内のisLoggedInメソッドのみなので、

const store = {
  getters: {
    isLoggedIn: jest.fn(() => true)
  }
}

↑みたいな感じでstore.getters.isLoggedInが機能するようなモックを作成して、shallowMountに渡していきます!

somePage.spec.js
import { shallowMount } from '@vue/test-utils'
import SomePage from '~/pages/somePage'

describe('SomePage', () => {
  let wrapper, store

  beforeEach(() => {
    wrapper = shallowMount(SomePage, {
      mocks: { $store: store }
    })
  })

  describe('when logged in', () => {
    beforeAll(() => {
      store = {
        getters: {
          isLoggedIn: jest.fn(() => true)
        }
      }
    })

    it('shows logged in text', () => {
      expect(wrapper.text()).toContain('ログインしています😊')
    })
  })
})

$routerを使った例

Vue

somePage.vue
<template>
  <div class="home" @click="pushToHome()">
    ホーム
  </div>
</template>

<script>
export default {
  methods: {
    pushToHome() {
      this.$router.push('/')
    }
  }
}
</script>

「nuxt-link使えよ!!!」っていう話なんですが、例のためなので今回は許してください。笑

テスト

今回使っているのは$router.pushというメソッドなので、$storeをモックしたときと同様、

const router = { push: jest.fn() }

↑こんな感じでrouter.pushが機能するようなモックをshallowMountに渡します。

somePage.spec.js
import { shallowMount } from '@vue/test-utils'
import SomePage from '~/pages/somePage'

describe('SomePage', () => {
  let wrapper
  const router = { push: jest.fn() }

  beforeEach(() => {
    wrapper = shallowMount(SomePage, {
      mocks: { $router: router }
    })
  })

  describe('when home is clicked', () => {
    beforeEach(() => {
      const home = wrapper.find('.home')
      home.trigger('click')
    })

    it('pushes to home', () => {
      expect(router.push).toBeCalledWith('/')
    })
  })
})

asyncDataやfetched内でcontextをモックする方法

asyncDataとfetchedはnuxtが用意してくれている関数なので、vue-test-utilsのmountを使ってテストをしようとしても、asyncDataは実行されません。
なので、こちらから手動で実行させる必要があります。

asyncDataでstoreを使った例

Vue

somePage.vue
<template>
  <div>
    <p v-if="isLoggedIn">
      ログインしています😊
    </p>
    <p v-if="!isLoggedIn">
      ログインしていません😢
    </p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      isLoggedIn: false
    }
  },

  asyncData({ store }) {
    return { isLoggedIn: store.getters.isLoggedIn }
  }
}
</script>

テスト

「asyncDataやfetch以外でモックする方法」でもやったように、store.getters.isLoggedInが機能するようなstoreのモックを作ります。
ただ、今回はshallowMountmocksに渡すのではなく、asyncDataを呼び出す際に直接渡します。

somePage.spec.js
import { shallowMount } from '@vue/test-utils'
import SomePage from '~/pages/somePage'

describe('SomePage', () => {
  let wrapper, store

  beforeEach(() => {
    wrapper = shallowMount(SomePage)
    // 1. asyncDataを呼び出す
    const data = wrapper.vm.$options.asyncData({ store })
    // 2. asyncDataが返す値をVue instanceのデータに設定する
    wrapper.setData(data)
  })

  describe('when logged in', () => {
    beforeAll(() => {
      store = {
        getters: {
          isLoggedIn: jest.fn(() => true)
        }
      }
    })

    it('shows logged in text', () => {
      expect(wrapper.text()).toContain('ログインしています😊')
    })
  })
})

store以外にも、asyncData内でapperrorなどを使う場合も、この例と同様にモックできます。

最後に

以上を使えば、nuxt特有のメソッドを簡単にモックできるはずです!
プラグインのモックの方法も、需要があれば後々記事を書くかもしれません。
筆者はまだnuxtを使い始めたばかりなので、間違いやよりよい方法があればガシガシご指摘ください!

24
15
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?