N-LAB

Nuxt 3 × Piniaでストアの単体テストを実行する


目標


前提

※本手順書ではソースディレクトリを「src」に変更している想定としています。テストコードは「src/unitTest」に保存します。

https://n-laboratory.jp/articles/nuxt3-vitest-unittest

・Nuxt 3.4.3
・Vitest 0.31.0
・Pinia 2.0.36
・@pinia/nuxt 0.4.10
・@pinia/testing 0.1.0

目次

  1. Piniaインストール
  2. ストアの実装
  3. VitestのPinia初期設定
  4. 単体テストコードの実装


Piniaインストール


1. 「package.json」の「overrides」に以下を追加します。

{
  "overrides": {
    "vue": "latest"
  }
}


2. Piniaをインストールします。

$ npm install pinia @pinia/nuxt


3. 以下のエラーが出る場合は「package.json」の「overrides」のvueのバージョンを直接指定する必要があります。

npm ERR! Invalid comparator: latest

※以下のように修正し、再度上記コマンドを実行することで正しくPiniaがインストールされるようになります。

{
  "overrides": {
    "vue": "3.3.2"
  }
}


4. 「nuxt.config.ts」の「modules」に以下を追加します。

export default defineNuxtConfig({
  modules: ['@pinia/nuxt'],
  pinia: {
    autoImports: [
      // defineStoreの自動インポート
      'defineStore'
    ]
    // vuexも併用する場合は以下を追加
    // disableVuex: false
  }
});


ストアの実装

1. 「stores」ディレクトリに「user.ts」を新規作成し、以下を追加します。

// nuxt.config.tsのautoImportsにdefineStoreを追加している場合はこのimport文は不要です。
import { defineStore } from 'pinia'

type User = {
  email: string,
  password: string
}

type UserState = {
  user: User
}

export const useUserStore = defineStore('user', {
  state: (): UserState => ({
    // ユーザーの定義・初期化
    user: { email: '', password: '' }
  }),
  actions: {
    // ユーザー情報の更新
    setUserInfo (email: string, password: string) {
      this.user.email = email
      this.user.password = password
    }
  }
})


2. Vueファイルからストアを参照するには以下のように実装します。

// store.vue
<script lang="ts" setup>
import { useUserStore } from '../stores/user'

// storeの取得
const store = useUserStore()

// emailの取得
const email = store.user.email

// passwordの取得
const password = store.user.password

// ユーザー情報の更新
store.setUserInfo("new email", "new password")
</script>


VitestのPinia初期設定

Error: [🍍]: "getActivePinia()" was called but there was no active Pinia. Did you forget to install pinia?


1. @pinia/testingをインストールします。

$ npm install --save-dev @pinia/testing


2. テストコードの実装はbeforeEachの中でsetActivePinia関数をコールします

import { setActivePinia, createPinia } from 'pinia'

beforeEach(() => {
  setActivePinia(createPinia())
})

※実装に関して詳細は以下を参照ください。
https://pinia.vuejs.org/cookbook/testing.html#unit-testing-components

単体テストコードの実装

1. 「store.spec.ts」を新規作成し、以下を追加します。

import { beforeEach, describe, expect, test } from 'vitest'
import { setActivePinia, createPinia } from 'pinia'
import { useUserStore } from '@/stores/user'

const initialUser = {
  email: '',
  password: ''
}
const updatedUser = {
  email: 'new email',
  password: 'new password'
}

describe('Stores', () => {
  beforeEach(() => {
    setActivePinia(createPinia())
  })

  test('ストアのユーザー情報が初期化されていること', () => {
    // Arrange
    const store = useUserStore()

    // Assert
    expect(store.user).toEqual(initialUser)
  })

  test('setUserInfoを呼び出した場合ストアのユーザー情報が更新されること', () => {
    // Arrange
    const store = useUserStore()

    // Act
    store.setUserInfo(updatedUser.email, updatedUser.password)

    // Assert
    expect(store.user).toEqual(updatedUser)
  })
})


2. 「store.spec.ts」のテストを実行します。全件passすることを確認します。

$ npm run test
> test
> vitest
 ✓ src/unitTest/store.spec.ts (2)
     ✓ Stores (2)
     ✓ ストアのユーザー情報が初期化されていること
     ✓ setUserInfoを呼び出した場合, ストアのユーザー情報が更新されること
 Test Files  1 passed (1)
      Tests  2 passed (2)

※本手順書では「package.json」の「scripts」に以下が追加されている想定としています。

{
  "scripts": {
    "test": "vitest",
  },
}



以上で全ての手順は完了になります