My component and Pinia store are working flawlessly in the browser and E2E tests using Cypress, but they fail when it comes to running unit tests. I am utilizing vue-testing-utils and vitest for testing.
In the unit test, calling a function from the store works fine when triggered by a button click. However, if the function is called within the mounted or main script, the test fails.
src/components/UsersComponent.vue
<script setup>
import { onMounted } from 'vue'
import { useUsersStore } from '@/stores/users.store'
const usersStore = useUsersStore()
onMounted(() => {
usersStore.resetStatus()
})
function changeStatus() {
usersStore.changeStatus()
}
</script>
<template>
<div>
<p>Status: {{ usersStore.status }}</p>
<button @click="changeStatus()">Change Status</button>
</div>
</template>
src/stores/users.store.js
import { defineStore } from 'pinia'
import { usersAPI } from '@/gateways'
export const useUsersStore = defineStore({
id: 'users',
persist: true,
state: () => ({
status: 'ready',
}),
actions: {
resetStatus() {
this.status = 'ready'
},
changeStatus() {
this.status = 'loading'
},
},
})
src/components/tests/UsersComponent.spec.js
import { describe, it, expect, vi, beforeEach } from 'vitest'
import { mount } from '@vue/test-utils'
import { createTestingPinia } from '@pinia/testing'
import UsersComponent from '@/components/UsersComponent.vue'
import { useUsersStore } from '@/stores/users.store'
const wrapper = mount(UsersComponent, {
global: {
plugins: [createTestingPinia({ createSpy: vi.fn() })],
},
})
const usersStore = useUsersStore()
describe('UsersComponent', () => {
it('store function is called', async () => {
// arrange
const spy = vi.spyOn(usersStore, 'resetStatus')
const button = wrapper.find('button')
// act
await button.trigger('click')
// assert
expect(spy).toHaveBeenCalled()
})
})
The unit tests throw two different errors. The first error occurs as a console log when trying to run the function inside onMounted()
, while the second error is what vitest returns.
stderr | unknown test
[Vue warn]: Unhandled error during execution of mounted hook
at <UsersComponent ref="VTU_COMPONENT" >
at <VTUROOT>
FAIL src/components/__tests__/UsersComponent.spec.js [ src/components/__tests__/UsersComponent.spec.js ]
TypeError: usersStore.resetStatus is not a function
❯ src/components/UsersComponent.vue:16:14
16|
17| <template>
18| <div>
| ^
19| <p>Status: {{ usersStore.status }}</p>
20| <button @click="changeStatus()">Change Status</button>
Although this example may seem basic, I'm curious about how to integrate store functions inside onMounted()
or similar places without causing issues in all unit tests.