我在用笑话测试嵌套 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
},
},
})
即使不检查 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()
...