Store yang sehat adalah store yang bisa diuji. Episode ini membahas createTestingPinia untuk pinia tiruan, reset state antar test, mocking action dan API dengan vi.fn dan MSW, testing getter, serta component testing dengan Vue Test Utils dan Vitest.

Kode tanpa test adalah bom waktu — terutama state management yang dipakai banyak komponen. Menjawab kebutuhan ini, tim Pinia menyediakan @pinia/testing: utility untuk membuat pinia tiruan yang memudahkan testing store dan komponen.
Episode 17 membahas testing Pinia secara menyeluruh: createTestingPinia, reset state antar test, mocking action dan API, testing getter, serta component testing dengan Vue Test Utils dan Vitest.
Install peralatan testing terlebih dahulu:
npm i -D vitest @vue/test-utils @pinia/testingUntuk test unit store, aktifkan pinia tiruan dengan createTestingPinia:
import { setActivePinia } from 'pinia'
import { createTestingPinia } from '@pinia/testing'
import { beforeEach } from 'vitest'
beforeEach(() => {
setActivePinia(createTestingPinia({ createSpy: vi.fn }))
})createTestingPinia({ createSpy: vi.fn }) membuat pinia di mana setiap action otomatis menjadi spy. Di setiap test, setActivePinia menjamin state bersih — tidak ada kebocoran antar test.
Karena action menjadi spy, kalian bisa mengecek pemanggilan tanpa menjalankan efek samping aslinya:
import { useCounterStore } from '@/stores/counter'
import { createTestingPinia } from '@pinia/testing'
it('memanggil action increment', () => {
const pinia = createTestingPinia({ createSpy: vi.fn })
const store = useCounterStore(pinia)
store.increment()
expect(store.increment).toHaveBeenCalledTimes(1)
})useCounterStore(pinia) memakai instance pinia tiruan secara eksplisit. Action increment tidak benar-benar menambah state — ia menjadi spy, sehingga test fokus pada perilaku pemanggilan.
Untuk menguji logika yang bergantung pada state tertentu, lewatkan initialState:
const pinia = createTestingPinia({
initialState: {
cart: { items: [{ name: 'Kopi', price: 15000, qty: 2 }] },
},
})
const store = useCartStore(pinia)
expect(store.totalPrice).toBe(30000)initialState: { cart: {...} } mengisi state store cart sebelum test berjalan. Ini cara paling nyaman untuk menguji getter dengan data yang disiapkan.
Untuk action async, mock fetch agar tidak menyentuh jaringan:
it('mengisi profile dari API', async () => {
vi.stubGlobal('fetch', vi.fn().mockResolvedValue({
ok: true,
json: () => Promise.resolve({ name: 'Arman' }),
}))
const store = useUserStore()
await store.fetchProfile()
expect(store.profile?.name).toBe('Arman')
})vi.stubGlobal('fetch', ...) mengganti fetch global dengan mock. Untuk project yang lebih besar, gunakan MSW untuk menangani banyak endpoint secara realistis.
Terakhir, uji komponen yang memakai store dengan Vue Test Utils:
import { mount } from '@vue/test-utils'
import CounterView from '@/components/CounterView.vue'
it('merender nilai dari store', () => {
const wrapper = mount(CounterView, {
global: { plugins: [createTestingPinia()] },
})
expect(wrapper.text()).toContain('Nilai: 0')
})global: { plugins: [createTestingPinia()] } menyuntikkan pinia tiruan ke seluruh komponen di bawah test. Komponen berjalan persis seperti di produksi, tetapi semua aksi store terkontrol.
Tip
Fokuskan test pada perilaku: panggilan action, hasil getter, dan apa yang dirender. Jangan test detail implementasi Vue yang sudah ditangani framework itu sendiri.
Episode 17 membekali kalian tooling testing yang lengkap. Kalian sekarang bisa membuat pinia tiruan dengan createTestingPinia, mereset state antar test, menginisialisasi state, mocking API dan action, serta melakukan component testing.
Inti yang harus dibawa pulang:
createTestingPinia({ createSpy: vi.fn }) membuat action jadi spy.setActivePinia di beforeEach menjaga state tetap bersih.initialState mengisi state awal untuk menguji getter.vi.fn atau MSW untuk action async.global.plugins di Vue Test Utils.Di episode 18 selanjutnya kita akan membahas custom plugin dan lifecycle lanjutan — memakai $onAction untuk tracking, subscribe yang menulis ke JSON, dan plugin global untuk analytics serta error handler. Ini menyempurnakan kemampuan plugin dari episode 8.