Maison  >  Questions et réponses  >  le corps du texte

La fonction de Vue Pinia n'est pas définie dans onMounted lors de l'exécution de tests unitaires

J'ai un composant et un magasin Pinia qui contiennent l'état et certaines opérations. Le code fonctionne parfaitement dans les tests de navigateur et E2E (cyprès), mais échoue dans les tests unitaires. J'utilise vue-testing-utils et vitest.

L'appel d'une fonction stockée à partir d'un test unitaire fonctionne correctement lorsque le bouton est cliqué, mais si la fonction est installée ou dans le script principal, le test échoue

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/test/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()
  })
})

Le test unitaire renvoie 2 erreurs différentes. Le premier est le journal de la console lorsque la fonction tente de s'exécuter dans onMounted() et le second est ce que renvoie Vitest.

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>

Je sais que cet exemple est un peu basique et ne sert pas vraiment à l'objectif, mais j'aimerais savoir comment stocker des fonctions dans onMounted() (ou quelque part similaire) sans casser tous mes tests unitaires.

P粉103739566P粉103739566323 Il y a quelques jours689

répondre à tous(1)je répondrai

  • P粉451614834

    P粉4516148342023-11-01 14:56:54

    Peut-être que cela vous sera utile :

    describe('UsersComponent',  () => {
      it('changeStatus function is called', async () => {
        const wrapper = mount(UsersComponent, {
          mounted: vi.fn(), // With this you mock the onMounted
          global: {
            plugins: [createTestingPinia({
              initialState: { // Initialize the state
                users: { status: 'ready' }, 
              }
            })]
          }
        })  
      
        // Spy the method you call...
        const spy = vi.spyOn(wrapper.vm, 'changeStatus');
    
        wrapper.vm.changeStatus()
    
        expect(spy).toHaveBeenCalled()
        expect(spy).toHaveBeenCalledTimes(1)
      })
    })

    répondre
    0
  • Annulerrépondre