我的 Vue 3 应用程序中有一个组件,它显示一个复选框。 该复选框可以由用户手动选中,但也可以由于 Pinia 状态更改而选中/取消选中。我对单元测试很陌生,但我认为这个组件的一个好的单元测试将包括检查复选框是否正确地对 Pinia 状态做出反应。 但是,在我的单元测试中,当我更改 Pinia 状态时,复选框值不会更改(组件本身工作正常,仅在单元测试中不起作用)。 有谁知道我做错了什么?
除了调用存储操作来更新状态外,我还尝试了 store.$patch,这也不起作用。
这是我的组件:
<template>
<div class="field-checkbox">
<Checkbox role="checkbox" :aria-label="displayName" @change="checkGroupMember()" v-model="checked" :binary="true" />
<label>{{displayName}}</label>
</div>
</template>
<script setup lang="ts">
import { useContactBookStore } from "@/stores/contactBookStore";
import { ref, watch } from "vue";
import { storeToRefs } from "pinia";
const store = useContactBookStore();
const props = defineProps({
groupMember: { type:Object, required: true }
});
const checked = ref(false);
const { getCheckedGroupMembers } = storeToRefs(store)
const displayName = ref(props.groupMember.title + " " + props.groupMember.firstName + " " + props.groupMember.lastName);
// set the initial value of the checkbox
updateCheckBox();
// watch the value of getCheckedGroupMembers in the store and if it
// changes re-evaluate the value of the checkbox
watch(getCheckedGroupMembers , () => {
updateCheckBox();
},{ deep: true })
// when the checkbox is checked/unchecked, run the checkUser method
// in the store
function checkGroupMember() {
const groupMember = {
id:props.groupMember.id,
title:props.groupMember.title,
firstName:props.groupMember.firstName,
lastName:props.groupMember.lastName
}
store.checkGroupMember(groupMember,checked.value);
}
// the checkbox is checked if the user is among the checked users
// in the store
function updateCheckBox() {
const groupMember = {
id: props.groupMember.id,
title: props.groupMember.title,
firstName: props.groupMember.firstName,
lastName: props.groupMember.lastName
}
const exists = getCheckedGroupMembers.value.find((member) => member.id === groupMember.id)
checked.value = !!exists;
}
</script>
这是我的单元测试:
import { render, screen } from "@testing-library/vue";
import GroupMember from "@/components/ContactBook/GroupMember.vue";
import { describe, it, vi, expect, beforeEach, afterEach } from "vitest";
import { createTestingPinia } from "@pinia/testing";
import PrimeVue from "primevue/config";
import { createPinia, setActivePinia } from "pinia";
import Checkbox from 'primevue/checkbox';
import { useContactBookStore } from "@/stores/contactBookStore";
describe("GroupMember", () => {
const mockUser:GroupMember = {id:"TT001",title:"Mr",firstName:"Ted",lastName:"Tester"}
let mockProps = {groupMember:mockUser};
render(GroupMember, {
props: mockProps,
global: {
components: {Checkbox},
plugins: [PrimeVue,
createTestingPinia({
initialState: {contactBook:{checkedGroupMembers:[mockUser]}},
stubActions: false,
createSpy: vi.fn,
fakeApp:true
}),
],
},
});
setActivePinia(createPinia());
it("Displays the user name in the correct format", async() => {
const displayName = mockProps.groupMember.title + " " + mockProps.groupMember.firstName + " " + mockProps.groupMember.lastName;
screen.getByText(displayName)
});
it("Shows the checkbox initially checked", async() => {
let checkbox:any;
const displayName = mockProps.groupMember.title + " " + mockProps.groupMember.firstName + " " + mockProps.groupMember.lastName;
checkbox = screen.getAllByRole("checkbox", { name: displayName })[1]
expect(checkbox.checked).toBe(true)
});
it("Should display the checkbox as unchecked when the store is updated", async() => {
let checkbox:any;
const displayName = mockProps.groupMember.title + " " + mockProps.groupMember.firstName + " " + mockProps.groupMember.lastName;
checkbox = screen.getAllByRole("checkbox", { name: displayName })[1]
const store = useContactBookStore();
await store.checkGroupMember(mockUser,false);
//await store.$patch({checkedGroupMembers:[]}) // this didn't work either
expect(checkbox.checked).toBe(false)
});
});
这是我在测试运行时遇到的错误:
54| expect(checkbox.checked).toBe(false)
| ^
55| });
56| });
- Expected "false"
+ Received "true"
当您在单元测试中渲染或挂载组件时,没有运行事件循环,因此虽然您可以在 Pinia 存储中更改状态,但组件直到"稍后"才会对更改做出反应:import { flushPromises } from '@vue/test-utils'; await flushPromises()
、await component.vm.$nextTick
或import { nextTick } from 'vue'; await nextTick()
。
请参阅 https://v1.test-utils.vuejs.org/guides/testing-async-components.html 其中描述您可以await
触发器,例如单击复选框,但如果更改发生在带外,您不一定有足够的等待时间。
同花顺承诺记录在这里