💚
Nuxt3+VitestでuseStateのテストを書く
Nuxt3で提供されているuseStateを使用したcomposableのテストを書く必要があり、mockを作成してテストを書きました。vitestを使うことと、テストを書くことの経験が浅いので、もっと良い書き方があるかもしれません。
nuxtは3.0.0-rc.8
, vitestは0.21.1
を使用しています。
方針
Nuxt3のAuto importsによって各関数等のimport
を書かずに済みます。このことを利用して、テストではReference ErrorとなるuseState
を'グローバル関数'としてモックします。
テスト対象
以下のような簡単なcomposableを考えてみます。
useSomething.ts
import { readonly } from 'vue'
export const useSomething = () => {
const state = useState('something', () => {
return {
hoge: true,
}
})
const toggleHoge = () => {
state.value.hoge = !state.value.hoge
}
return {
state: readonly(state),
toggleHoge,
}
}
テストコード
useStateMock
はnuxt3のuseStateの実装を引っ張ってきて、一部を書き換えています。
useSomething.test.ts
import { describe, vi, test, expect } from 'vitest'
import { reactive, toRef, isRef, Ref } from 'vue'
import { useSomething } from 'composables/useSomething'
describe('useSomething', () => {
// Nuxtのpayloadの一部をmockする
const payload = reactive<{ state: Record<string, any> }>({
state: {},
})
// useStateをmockする
const useStateMock = vi.fn((key: string, init?: () => any) => {
const state = toRef(payload.state, key)
if (state.value === undefined && init) {
const initialValue = init()
if (isRef(initialValue)) {
payload.state[key] = initialValue
return initialValue as Ref<any>
}
state.value = initialValue
}
return state
})
// モックをグローバルに使えるようにする
vi.stubGlobal('useState', useStateMock)
test('Stateが取得できる', () => {
const smth = useSomething()
expect(smth.state.value).toEqual({ hoge: true })
})
test('Stateが変更できる', () => {
const smth = useSomething()
smth.toggleHoge()
expect(smth.state.value).toEqual({ hoge: false })
})
test('Stateの変更が共有される', () => {
const smth = useSomething()
// NOTE: 一つ前のテストでhogeの値が変わったままのはず
expect(smth.state.value).toEqual({ hoge: false })
})
})
Discussion