使用 Jest 模拟另一家商店使用的 Pinia 商店操作

问题描述 投票:0回答:1

我在用笑话测试嵌套 pinia 存储操作时遇到困难。

我有以下笑话测试。当我运行此测试时,我收到类型错误

TypeError: foodStore.getSnack.mockReturnValue is not a function

如果我取消注释这行测试

// foodStore.getSnack = jest.fn()

它过去了。我不介意它过去,但这对我来说有点臭。 pinia 是否有模拟动作的方法,或者在创建对象后重新模拟动作是否正确?

import { setActivePinia, createPinia, getActivePinia } from 'pinia'
import { useMamaStore } from 'src/stores/mama'
import { useFoodStore } from 'src/stores/food'
export const getStore = (name) => {
  const store = getActivePinia()?._s.get(name)
  if (!store) throw new Error(`${name} store does not exist`)
  return store
}

jest.mock(
  'src/stores/food',
  () => {
    const { defineStore } = require('pinia')
    const useFoodStore = defineStore('food', {
      state: () => ({ snacks: 10 }),
      actions: {
        getSnack: jest.fn(),
      },
    })
    return { useFoodStore }
  },
)
describe('useMamaStore', () => {
  let mamaStore
  let foodStore

  beforeEach(() => {
    const pinia = createPinia()
    setActivePinia(pinia)
    foodStore = useFoodStore(pinia)
    // foodStore.getSnack = jest.fn()
    mamaStore = useMamaStore(pinia)

    jest.clearAllMocks() 
  })


  it('should make a snack if food store has snacks available', () => {
    // Mock food store to return a valid snack
    foodStore.getSnack.mockReturnValue(true)
    mamaStore.makeSnack()
    expect(foodStore.getSnack).toHaveBeenCalled()
    expect(mamaStore.snackMade).toBe(true) 
  })

})

● useMamaStore › should make a snack if food store has snacks available

TypeError: foodStore.getSnack.mockReturnValue is not a function

    58 |   it('should make a snack if food store has snacks available', () => {
    59 |     // Mock food store to return a valid snack
  > 60 |     foodStore.getSnack.mockReturnValue(true)
       |                        ^
    61 |     mamaStore.makeSnack()
    62 |     expect(foodStore.getSnack).toHaveBeenCalled()
    63 |     expect(mamaStore.snackMade).toBe(true) 

    at Object.mockReturnValue
      (test/jest/__tests__/stores/mama.jest.spec.js:60:24)

// src/stores/mama.js
import { defineStore } from 'pinia'
import { useFoodStore } from './food'

export const useMamaStore = defineStore('mama', {
  state: () => ({
    loving: true,
    caring: true,
    snackMade: false,
  }),
  getters: {
    timeForSnack(state) {
      return state.snackMade
    },
  },
  actions: {
    makeSnack() {
      const foodStore = useFoodStore()
      const snack = foodStore.getSnack()
      this.snackMade = snack
    },
  },
})
// src/stores/food.js
import { defineStore } from 'pinia'

export const useFoodStore = defineStore('food', {
  state: {
    delicious: true,
    snacks: 10,
  },
  getters,
  actions: {
    getSnack() {
      if (this.snacks === 0) {
        return false
      }
      this.snacks = this.snacks - 1
      return true
    },
  },
})
vue.js unit-testing jestjs pinia
1个回答
0
投票

即使不检查 Pinia 操作的实现方式,也可以预期

foodStore.getSnack
actions.getSnack
选项中提供的功能不同,而是它的包装器,因此
foodStore.getSnack
不是 Jest 间谍。一个操作应该绑定到上下文,因此它可以从存储对象中解构,并且调用一个操作应该调度它,如 Pinia devtools 中所示。

但是可以预期

foodStore.getSnack
会调用
actions.getSnack
,因此测试策略与模拟模块中本地使用的任何模拟或间谍函数相同,应保留对间谍的引用,以便在测试。
jest.mock
的提升限制了间谍在测试模块中可用的方式,这可以通过将其定义为模块导出并导入来解决:

import { useFoodStore, getSnackMock } from 'src/stores/food'

jest.mock(
  'src/stores/food',
  () => {
    const getSnackMock = jest.fn();
    ...
      actions: { getSnack: getSnackMock }
    })
    return { useFoodStore, getSnackMock };
  },
)

...

getSnackMock.mockReturnValue(true)
mamaStore.makeSnack()
...
© www.soinside.com 2019 - 2024. All rights reserved.