Probando Pinia
Pruebas de Tiendas
Las tiendas, por diseño, se utilizarán en muchos lugares y pueden hacer que las pruebas sean mucho más difíciles de lo que deberían ser. Afortunadamente, esto no tiene por qué ser así. Debemos tener en cuenta tres cosas al probar las tiendas:
- La instancia
pinia
: las tiendas no pueden funcionar sin ella actions
: la mayoría de las veces contienen la lógica más compleja de nuestras tiendas. ¿No sería bueno si ellas fueran simuladas por defecto?- Complementos: si confía en los complementos, también deberá instalarlos para las pruebas
Dependiendo de qué o cómo esté probando, debemos ocuparnos de estos tres de manera diferente:
Unidad de prueba de una tienda
Para realizar una prueba unitaria de una tienda, la parte más importante es crear una instancia de pinia
:
// counterStore.spec.ts
import { setActivePinia, createPinia } from 'pinia'
import { useCounter } from '@/stores/counter'
describe('Counter Store', () => {
beforeEach(() => {
// creates a fresh pinia and make it active so it's automatically picked
// up by any useStore() call without having to pass it to it:
// `useStore(pinia)`
setActivePinia(createPinia())
})
it('increments', () => {
const counter = useCounter()
expect(counter.n).toBe(0)
counter.increment()
expect(counter.n).toBe(1)
})
it('increments by amount', () => {
const counter = useCounter()
counter.increment(10)
expect(counter.n).toBe(10)
})
})
Si tiene complementos de la tienda, hay una cosa importante que debe saber: los complementos no se utilizarán hasta que pinia
esté instalado en una aplicación. Esto se puede solucionar creando una aplicación vacía o una falsa:
import { setActivePinia, createPinia } from 'pinia'
import { createApp } from 'vue'
import { somePlugin } from '@/stores/plugin'
// same code as above...
// you don't need to create one app per test
const app = createApp({})
beforeEach(() => {
const pinia = createPinia().use(somePlugin)
app.use(pinia)
setActivePinia(pinia)
})
Componentes de pruebas unitarias
Esto se puede lograr con createTestingPinia()
, que devuelve una instancia de pinia
diseñada para ayudar a los componentes de pruebas unitarias.
Comience instalando @pinia/testing
:
npm i -D @pinia/testing
Y asegúrese de crear una pruea de pinia
en sus pruebas al montar un componente:
import { mount } from '@vue/test-utils'
import { createTestingPinia } from '@pinia/testing'
const wrapper = mount(Counter, {
global: {
plugins: [createTestingPinia()],
},
})
const store = useSomeStore() // uses the testing pinia!
// state can be directly manipulated
store.name = 'my new name'
// can also be done through patch
store.$patch({ name: 'new name' })
expect(store.name).toBe('new name')
// actions are stubbed by default, meaning they don't execute their code by default.
// See below to customize this behavior.
store.someAction()
expect(store.someAction).toHaveBeenCalledTimes(1)
expect(store.someAction).toHaveBeenLastCalledWith()
Tenga en cuenta que si está utilizando Vue 2, @vue/test-utils
requiere una configuración ligeramente diferente.
Estado inicial
Puede establecer el estado inicial de todas sus tiendas al crear un pinia de prueba pasando un objeto initialState
. Este objeto será utilizado por el pinia
de prueba para parchear (patch
) las tiendas cuando se creen. Digamos que desea inicializar el estado de esta tienda:
import { defineStore } from 'pinia'
const useCounterStore = defineStore('counter', {
state: () => ({ n: 0 }),
// ...
})
Dado que la tienda se llama "counter", debe agregar un objeto coincidente a initialState
:
// somewhere in your test
const wrapper = mount(Counter, {
global: {
plugins: [
createTestingPinia({
initialState: {
counter: { n: 20 }, // start the counter at 20 instead of 0
},
}),
],
},
})
const store = useSomeStore() // uses the testing pinia!
store.n // 20
Personalización del comportamiento de las acciones
createTestingPinia
excluye todas las acciones de la tienda a menos que se indique lo contrario. Esto le permite probar sus componentes y tiendas por separado.
Si desea revertir este comportamiento y normalmente ejecutar sus acciones durante las pruebas, especifique stubActions: false
cuando llame a createTestingPinia
:
const wrapper = mount(Counter, {
global: {
plugins: [createTestingPinia({ stubActions: false })],
},
})
const store = useSomeStore()
// Now this call WILL execute the implementation defined by the store
store.someAction()
// ...but it's still wrapped with a spy, so you can inspect calls
expect(store.someAction).toHaveBeenCalledTimes(1)
Especificación de la función createSpy
Al usar Jest o Vitest con globals: true
, createTestingPinia
automáticamente agrega acciones utilizando la función de espionaje basada en el marco de prueba existente (jest.fn
o vitest.fn
). Si está utilizando un marco diferente, deberá proporcionar una opción createSpy:
import sinon from 'sinon'
createTestingPinia({
createSpy: sinon.spy, // use sinon's spy to wrap actions
})
Puede encontrar más ejemplos en las pruebas del paquete de pruebas.
Simulando captadores
De forma predeterminada, cualquier getter se calculará como un uso normal, pero puede forzar manualmente un valor configurando el getter en lo que desee:
import { defineStore } from 'pinia'
import { createTestingPinia } from '@pinia/testing'
const useCounter = defineStore('counter', {
state: () => ({ n: 1 }),
getters: {
double: (state) => state.n * 2,
},
})
const pinia = createTestingPinia()
const counter = useCounter(pinia)
counter.double = 3 // 🪄 getters are writable only in tests
// set to undefined to reset the default behavior
// @ts-expect-error: usually it's a number
counter.double = undefined
counter.double // 2 (=1 x 2)
Complementos de Pinia
Si tiene complementos pinia
, asegúrese de pasarlos cuando llame a createTestingPinia()
para que se apliquen correctamente. No los agregue con testingPinia.use(MyPlugin)
como lo haría con un pinia
normal:
import { createTestingPinia } from '@pinia/testing'
import { somePlugin } from '@/stores/plugin'
// inside some test
const wrapper = mount(Counter, {
global: {
plugins: [
createTestingPinia({
stubActions: false,
plugins: [somePlugin],
}),
],
},
})
Pruebas E2E
Cuando se trata de pinia
, no necesita cambiar nada para las pruebas e2e, ¡ese es el objetivo de las pruebas e2e! Tal vez podría probar las solicitudes HTTP, pero eso está más allá del alcance de esta guía 😄.
Componentes de prueba unitaria (Vue 2)
Cuando utilice Vue Test Utils 1, instale Pinia en un localVue
:
import { PiniaVuePlugin } from 'pinia'
import { createLocalVue, mount } from '@vue/test-utils'
import { createTestingPinia } from '@pinia/testing'
const localVue = createLocalVue()
localVue.use(PiniaVuePlugin)
const wrapper = mount(Counter, {
localVue,
pinia: createTestingPinia(),
})
const store = useSomeStore() // uses the testing pinia!