'Vue Pinia function is undefined in onMounted when unit test is ran

I have a component and a Pinia store which contains a state and some actions. The code works perfectly fine in browser and in E2E (cypress) tests, but fail on unit tests. I'm using vue-testing-utils and vitest.

The store function can be called fine from the unit test when the button is clicked, but if the function is in the mounted or main script, it fails the test

src/components/UsersComponent.vue

<script setup>
import { onMounted } from 'vue'
import { useUsersStore } from '@/stores/users.store'

const usersStore = useUsersStore()
// usersStore.resetStatus() // <- This fails in the unit test

onMounted(() => {
  usersStore.resetStatus() // <- This fails in the unit test
})

function changeStatus() {
  usersStore.changeStatus() // <- This passes in the unit test
}
</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',
  }),

  getters: {},

  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 return 2 different error. The first is a console log when the function tries to run in onMounted() and the second 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>

I know this example is a little basic and doesn't really serve a purpose, but I'm wondering how I can have store functions inside the onMounted() (or similar places) without it breaking all my unit tests.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source