Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Vue 3 testing best practices with Vitest, Vue Test Utils, component testing, mocking, and Playwright E2E.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
reference/testing-pinia-store-setup.md
1---2title: Configure Pinia Testing with createTestingPinia and setActivePinia3impact: HIGH4impactDescription: Missing Pinia configuration causes 'injection Symbol(pinia) not found' errors and failing tests5type: gotcha6tags: [vue3, testing, pinia, vitest, store, mocking, createTestingPinia]7---89# Configure Pinia Testing with createTestingPinia and setActivePinia1011**Impact: HIGH** - Testing components or composables that use Pinia stores without proper configuration results in "[Vue warn]: injection Symbol(pinia) not found" errors. Tests will fail or behave unexpectedly.1213Use `@pinia/testing` package with `createTestingPinia` for component tests and `setActivePinia(createPinia())` for unit testing stores directly.1415## Task Checklist1617- [ ] Install `@pinia/testing` as a dev dependency18- [ ] Use `createTestingPinia` in component tests with `global.plugins`19- [ ] Use `setActivePinia(createPinia())` in `beforeEach` for store unit tests20- [ ] Configure `createSpy: vi.fn` when NOT using `globals: true` in Vitest21- [ ] Initialize store inside each test to get fresh state22- [ ] Use `stubActions: false` when you need real action execution2324**Incorrect:**25```javascript26import { mount } from '@vue/test-utils'27import UserProfile from './UserProfile.vue'2829// BAD: Missing Pinia - causes injection error30test('displays user name', () => {31const wrapper = mount(UserProfile) // ERROR: injection "Symbol(pinia)" not found32expect(wrapper.text()).toContain('John')33})34```3536```javascript37import { useUserStore } from '@/stores/user'3839// BAD: No active Pinia instance40test('user store actions', () => {41const store = useUserStore() // ERROR: no active Pinia42store.login('john', 'password')43})44```4546**Correct - Component Testing:**47```javascript48import { mount } from '@vue/test-utils'49import { createTestingPinia } from '@pinia/testing'50import { vi } from 'vitest'51import UserProfile from './UserProfile.vue'52import { useUserStore } from '@/stores/user'5354// CORRECT: Provide testing pinia with stubbed actions55test('displays user name', () => {56const wrapper = mount(UserProfile, {57global: {58plugins: [59createTestingPinia({60createSpy: vi.fn, // Required if not using globals: true61initialState: {62user: { name: 'John', email: '[email protected]' }63}64})65]66}67})6869expect(wrapper.text()).toContain('John')70})7172// CORRECT: Test with stubbed actions (default behavior)73test('calls logout action', async () => {74const wrapper = mount(UserProfile, {75global: {76plugins: [createTestingPinia({ createSpy: vi.fn })]77}78})7980// Get store AFTER mounting with createTestingPinia81const store = useUserStore()8283await wrapper.find('[data-testid="logout"]').trigger('click')8485// Actions are stubbed and wrapped in spies86expect(store.logout).toHaveBeenCalled()87})88```8990**Correct - Store Unit Testing:**91```javascript92import { describe, it, expect, beforeEach, vi } from 'vitest'93import { setActivePinia, createPinia } from 'pinia'94import { useUserStore } from '@/stores/user'9596describe('User Store', () => {97beforeEach(() => {98// Create fresh Pinia instance for each test99setActivePinia(createPinia())100})101102it('initializes with empty user', () => {103const store = useUserStore()104expect(store.user).toBeNull()105expect(store.isLoggedIn).toBe(false)106})107108it('updates user on login', async () => {109const store = useUserStore()110111// Real action executes - not stubbed112await store.login('john', 'password')113114expect(store.user).toEqual({ name: 'John' })115expect(store.isLoggedIn).toBe(true)116})117118it('clears user on logout', () => {119const store = useUserStore()120store.user = { name: 'John' } // Set initial state121122store.logout()123124expect(store.user).toBeNull()125})126})127```128129## Testing with Real Actions vs Stubbed Actions130131```javascript132import { createTestingPinia } from '@pinia/testing'133134// Stubbed actions (default) - for isolation135const wrapper = mount(Component, {136global: {137plugins: [138createTestingPinia({139createSpy: vi.fn,140// stubActions: true (default) - actions are mocked141})142]143}144})145146// Real actions - for integration testing147const wrapper = mount(Component, {148global: {149plugins: [150createTestingPinia({151createSpy: vi.fn,152stubActions: false // Actions execute normally153})154]155}156})157```158159## Mocking Specific Action Implementations160161```javascript162import { mount } from '@vue/test-utils'163import { createTestingPinia } from '@pinia/testing'164import { vi } from 'vitest'165import { useCartStore } from '@/stores/cart'166167test('handles checkout failure', async () => {168const wrapper = mount(Checkout, {169global: {170plugins: [createTestingPinia({ createSpy: vi.fn })]171}172})173174const cartStore = useCartStore()175176// Mock specific action behavior177cartStore.checkout.mockRejectedValue(new Error('Payment failed'))178179await wrapper.find('[data-testid="checkout"]').trigger('click')180await flushPromises()181182expect(wrapper.find('.error').text()).toContain('Payment failed')183})184```185186## Spying on Actions with vi.spyOn187188```javascript189import { setActivePinia, createPinia } from 'pinia'190import { vi } from 'vitest'191import { useUserStore } from '@/stores/user'192193test('tracks action calls', async () => {194setActivePinia(createPinia())195const store = useUserStore()196197const loginSpy = vi.spyOn(store, 'login')198loginSpy.mockResolvedValue({ success: true })199200await store.login('john', 'password')201202expect(loginSpy).toHaveBeenCalledWith('john', 'password')203})204```205206## Testing Store $subscribe207208```javascript209import { setActivePinia, createPinia } from 'pinia'210import { useUserStore } from '@/stores/user'211212test('subscription triggers on state change', () => {213setActivePinia(createPinia())214const store = useUserStore()215216const callback = vi.fn()217store.$subscribe(callback)218219store.user = { name: 'John' }220221expect(callback).toHaveBeenCalled()222})223```224225## Reference226- [Pinia Testing Guide](https://pinia.vuejs.org/cookbook/testing.html)227- [@pinia/testing Package](https://www.npmjs.com/package/@pinia/testing)228- [Vue Test Utils - Plugins](https://test-utils.vuejs.org/guide/advanced/plugins.html)229