搜尋

首頁  >  問答  >  主體

執行單元測試時,Vue Pinia的函數在onMounted中未定義

我有一個元件和一個 Pinia 存儲,其中包含狀態和一些操作。該程式碼在瀏覽器和 E2E(cypress)測試中運行得非常好,但在單元測試中失敗。我正在使用 vue-testing-utils 和 vitest。

點擊按鈕時,可以從單元測試中很好地呼叫儲存函數,但如果函數位於已安裝或主腳本中,則測試會失敗

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

單元測試傳回 2 個不同的錯誤。第一個是函數嘗試在 onMounted() 中執行時的控制台日誌,第二個是 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>

我知道這個例子有點基本,並沒有真正達到目的,但我想知道如何在onMounted() (或類似的地方)中擁有存儲函數,而不破壞我的所有單元測試。

P粉103739566P粉103739566421 天前807

全部回覆(1)我來回復

  • P粉451614834

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

    也許這對您有用:

    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)
      })
    })

    回覆
    0
  • 取消回覆