Skip to content

Store 테스트

13.4.1. createTestingPinia

테스트 환경에서는 @pinia/testingcreateTestingPinia()를 사용하여 테스트용 Pinia 인스턴스를 생성합니다.

  • createTestingPinia()는 모든 action을 자동으로 모킹합니다.
  • stubActions: false를 지정하면 실제 action이 실행됩니다.
  • initialState로 Store의 초기 상태를 오버라이드할 수 있습니다.
typescript
import { createTestingPinia } from '@pinia/testing'
import { vi } from 'vitest'

// 기본 사용: 모든 action이 자동 모킹됩니다.
const pinia = createTestingPinia({
  createSpy: vi.fn,
})

// action을 실제로 실행하는 경우
const pinia = createTestingPinia({
  createSpy: vi.fn,
  stubActions: false,
})

// 초기 상태를 지정하는 경우
const pinia = createTestingPinia({
  createSpy: vi.fn,
  initialState: {
    user: { user: { id: 1, name: '테스트 사용자' }, loading: false },
    cart: { items: [{ id: 1, name: '상품A', price: 10000, quantity: 2 }] },
  },
})

13.4.2. Store 단위 테스트

Store를 컴포넌트 없이 독립적으로 테스트할 때는 setActivePinia()를 사용합니다.

typescript
// src/stores/__tests__/useCartStore.test.ts
import { describe, it, expect, beforeEach } from 'vitest'
import { setActivePinia, createPinia } from 'pinia'
import { useCartStore } from '../useCartStore'

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

  it('초기 상태는 빈 배열이어야 합니다', () => {
    const store = useCartStore()
    expect(store.items).toEqual([])
    expect(store.isEmpty).toBe(true)
  })

  it('항목 추가 시 totalPrice를 올바르게 계산해야 합니다', () => {
    const store = useCartStore()
    store.items.push({ id: 1, name: '상품A', price: 5000, quantity: 3 })

    expect(store.totalPrice).toBe(15000)
    expect(store.itemCount).toBe(1)
  })

  it('resetState 호출 시 초기 상태로 복원되어야 합니다', () => {
    const store = useCartStore()
    store.items.push({ id: 1, name: '상품A', price: 5000, quantity: 1 })

    store.resetState()

    expect(store.items).toEqual([])
  })
})
  • beforeEach에서 매번 새 Pinia 인스턴스를 생성하여 테스트 간 상태 오염을 방지합니다.
  • getter는 상태 변경 후 반환값을 검증합니다.

13.4.3. 컴포넌트 내 Store 테스트

컴포넌트에서 Store를 사용하는 경우, mountglobal.pluginscreateTestingPinia()를 주입합니다.

typescript
// src/components/__tests__/UserProfile.test.ts
import { describe, it, expect } from 'vitest'
import { mount } from '@vue/test-utils'
import { vi } from 'vitest'
import { createTestingPinia } from '@pinia/testing'
import UserProfile from '../UserProfile.vue'
import { useUserStore } from '@/stores/useUserStore'

describe('UserProfile', () => {
  it('사용자 이름을 표시해야 합니다', () => {
    const wrapper = mount(UserProfile, {
      global: {
        plugins: [
          createTestingPinia({
            createSpy: vi.fn,
            initialState: {
              user: {
                user: { id: 1, name: '홍길동' },
                loading: false,
              },
            },
          }),
        ],
      },
    })

    expect(wrapper.text()).toContain('홍길동')
  })

  it('마운트 시 loadCurrentUser를 호출해야 합니다', () => {
    const wrapper = mount(UserProfile, {
      global: {
        plugins: [createTestingPinia({ createSpy: vi.fn })],
      },
    })

    const userStore = useUserStore()
    expect(userStore.loadCurrentUser).toHaveBeenCalledOnce()
  })
})
  • initialState의 키는 defineStore에 전달한 Store ID와 일치해야 합니다.
  • 컴포넌트 마운트 후 useUserStore()를 호출하면 테스트용 Store 인스턴스를 반환합니다.

13.4.4. 모킹 패턴

API 호출 모킹

Store 내부의 API 호출은 vi.mock()으로 모킹합니다.

typescript
import { describe, it, expect, beforeEach, vi } from 'vitest'
import { setActivePinia, createPinia } from 'pinia'
import { useUserStore } from '../useUserStore'
import { fetchCurrentUser } from '@/api/user'

vi.mock('@/api/user', () => ({
  fetchCurrentUser: vi.fn(),
}))

describe('useUserStore - API 연동', () => {
  beforeEach(() => {
    setActivePinia(createPinia())
    vi.clearAllMocks()
  })

  it('loadCurrentUser 성공 시 사용자 정보를 저장해야 합니다', async () => {
    const mockUser = { id: 1, name: '테스트 사용자' }
    vi.mocked(fetchCurrentUser).mockResolvedValue(mockUser)

    const store = useUserStore()
    await store.loadCurrentUser()

    expect(store.user).toEqual(mockUser)
    expect(store.isLoggedIn).toBe(true)
    expect(store.loading).toBe(false)
  })
})

Action 모킹

createTestingPinia()를 사용하면 모든 action이 자동 모킹됩니다. 특정 action의 반환값을 지정하려면 mockResolvedValue()를 사용합니다.

typescript
const pinia = createTestingPinia({ createSpy: vi.fn })
const userStore = useUserStore()

vi.mocked(userStore.loadCurrentUser).mockResolvedValue(undefined)
  • stubActions: true(기본값)에서는 action 호출 여부만 검증합니다.
  • action의 실제 로직을 테스트하려면 stubActions: false를 지정하거나, Store 단위 테스트를 별도로 작성합니다.

TIENIPIA QUALIFIED STANDARD