You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue测试中Pinia Store状态未变更问题排查

问题描述

我想用Vitest测试submitEvaluation函数,预期调用disableSubmit(true)后,禁用状态设为true,此时submitEvaluation里的setIsLocked不应被执行。但实际调用disableSubmit(true)后,isDisabledSubmit始终是初始值false,导致setIsLocked仍被执行。我尝试通过wrapper.vm及直接导入useFormStore解决均无效,需排查问题原因。


相关代码

Pinia Store代码

lockStore

import { defineStore } from 'pinia';

export const useLockStore = defineStore("lockStore", {
    state: () => ({
        isLocked: false
    }),
    actions: {
        setIsLocked(value: boolean): void {
            this.isLocked = value;
        }
    },
    getters: {
        getIsLocked(state): boolean {
            return state.isLocked;
        }
    }
});

formStore

import { defineStore } from 'pinia';

export const useFormStore = defineStore("formStore", () => {
    const preventSubmit = ref(false);

    function disableSubmit(val: boolean): void {
        preventSubmit.value = val;
    }
    function isDisabledSubmit(): boolean {
        return preventSubmit.value;
    }

    return { disableSubmit, isDisabledSubmit: isDisabledSubmit() };
});

Vue组件(Composition API Setup语法)待测试函数

const { disableSubmit, isDisabledSubmit } = useFormStore();
function submitEvaluation(): void {
    console.log(isDisabledSubmit);

    if (!isDisabledSubmit) {
        lockStore.setIsLocked(false);
        updateEvaluation(payload.value, closeDialog);
    }
}

defineExpose({
    lockStore,
    loadDropDown,
    resubmissionDate,
    onDropDownReady,
    isOpenDialog,
    openDialog,
    closeDialog,
    cancelDialog,
    resetDataFields,
    dataFields,
    updateEvaluation,
    submitEvaluation,
    isDisabledSubmit,
    disableSubmit
})

测试文件代码

beforeEach(() => {
    // 创建新的Pinia并设为活跃状态,useStore()会自动使用它,无需手动传入
    setActivePinia(createPinia());
});

afterEach(() => {
    vi.clearAllMocks();
    vi.restoreAllMocks()
});


test.only('SubmitEvaluation_ifIsDisabledSubmitIsTrue_ExpectLockStoreSetLockedNotToBeCalled', async () => {
        const formStore = useFormStore();
        const lockStore = useLockStore();

        const spyOnFormStoreDisableSubmit = vi.fn(formStore.disableSubmit)
        formStore.disableSubmit = spyOnFormStoreDisableSubmit


        vi.spyOn(wrapper.vm, 'submitEvaluation')

        vi.spyOn(wrapper.vm, 'disableSubmit')

        vi.spyOn(formStore, 'disableSubmit')

        wrapper.vm.disableSubmit(true)
        wrapper.vm.isDisabledSubmit = vi.fn().mockReturnValue(true) as any
        console.log(wrapper.vm.isDisabledSubmit);

        formStore.disableSubmit(true)
        formStore.isDisabledSubmit = true
        wrapper.vm.isDisabledSubmit = vi.fn().mockReturnValue(true) as any
        wrapper.vm.submitEvaluation()
        // 当isDisabledSubmit为true时,setIsLocked不应被调用
        expect(wrapper.vm.lockStore.setIsLocked).toBeCalledTimes(0)
        // expect(lockStore.setIsLocked).toBeCalledTimes(0)

    })

问题根源与修复方案

问题核心

  1. formStore定义错误:在useFormStore中,isDisabledSubmit返回的是isDisabledSubmit()的执行结果(初始false),而非函数引用或响应式计算属性。这导致组件拿到的是一个固定布尔值,不会随preventSubmit的变化更新。
  2. 组件使用方式错误:组件解构出的isDisabledSubmit是静态值,不是函数/响应式对象,因此submitEvaluation中的判断永远用初始值。
  3. 测试操作无效:测试中直接给formStore.isDisabledSubmit或wrapper.vm.isDisabledSubmit赋值,无法同步组件内的静态值引用。

修复步骤

1. 修正formStore定义

选择以下两种方式之一:

  • 使用响应式计算属性:
import { defineStore, ref, computed } from 'pinia';

export const useFormStore = defineStore("formStore", () => {
    const preventSubmit = ref(false);

    function disableSubmit(val: boolean): void {
        preventSubmit.value = val;
    }
    const isDisabledSubmit = computed(() => preventSubmit.value);

    return { disableSubmit, isDisabledSubmit };
});
  • 返回函数引用:
import { defineStore, ref } from 'pinia';

export const useFormStore = defineStore("formStore", () => {
    const preventSubmit = ref(false);

    function disableSubmit(val: boolean): void {
        preventSubmit.value = val;
    }
    function isDisabledSubmit(): boolean {
        return preventSubmit.value;
    }

    return { disableSubmit, isDisabledSubmit }; // 不要加(),返回函数本身
});

2. 修正组件中的使用逻辑

  • 若用计算属性:
const { disableSubmit, isDisabledSubmit } = useFormStore();
function submitEvaluation(): void {
    console.log(isDisabledSubmit.value);

    if (!isDisabledSubmit.value) {
        lockStore.setIsLocked(false);
        updateEvaluation(payload.value, closeDialog);
    }
}
  • 若用函数:
const { disableSubmit, isDisabledSubmit } = useFormStore();
function submitEvaluation(): void {
    console.log(isDisabledSubmit());

    if (!isDisabledSubmit()) {
        lockStore.setIsLocked(false);
        updateEvaluation(payload.value, closeDialog);
    }
}

3. 简化测试代码

test.only('SubmitEvaluation_whenDisabled_shouldNotCallSetIsLocked', async () => {
    const formStore = useFormStore();
    const lockStore = useLockStore();

    // 监听setIsLocked方法
    const setIsLockedSpy = vi.spyOn(lockStore, 'setIsLocked');

    // 设置禁用状态
    formStore.disableSubmit(true);

    // 调用提交函数
    wrapper.vm.submitEvaluation();

    // 验证setIsLocked未被调用
    expect(setIsLockedSpy).not.toHaveBeenCalled();
})

内容的提问来源于stack exchange,提问作者venndi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 19:13:18