如何使用Jest测试Vue组件方法是否被调用?测试未触发报错如何解决
错误原因
- 间谍函数绑定对象错误、创建时机不对
你在组件实例化完成后才给App.methods.appenditem创建间谍,此时已经生成的wrapper实例已经拷贝了原始的方法定义,后续对原始组件配置的修改不会同步到已创建的实例上,间谍函数根本没有绑定到实际运行的实例,自然监听不到调用。 - 按钮默认处于禁用状态,点击事件不会生效
模板中q-btn配置了:disabled="quantity < 1 || newitem.length < 1",测试初始状态下newitem为空、quantity为null,按钮处于禁用状态,此时触发click事件不会执行绑定的appenditem方法。 - 未处理Vue异步更新逻辑
Vue的响应式更新、事件触发后的逻辑执行都是异步的,未等待异步逻辑执行完成就直接断言,会导致断言时机提前,获取不到正确的调用结果。
解决方案
- 调整间谍函数的绑定对象,直接绑定到已经生成的wrapper实例方法上
- 触发点击前先给表单字段赋值,解除按钮的禁用状态
- 测试用例改为异步,触发点击后等待
nextTick再执行断言 - 如果shallowMount对q-btn的自动stub导致事件绑定失效,可以在配置中排除q-btn的stub,或者直接使用mount挂载
修正后的测试代码
import App from "@/App.vue"; import { shallowMount, nextTick } from "@vue/test-utils"; describe("input-field.vue", () => { let wrapper; // 每个用例前重新挂载实例,避免用例之间数据污染 beforeEach(() => { wrapper = shallowMount(App, { // 排除q-btn的stub,保证事件绑定正常 stubs: { QBtn: false } }); }) it("renders", () => { expect(wrapper.exists()).toBe(true); }); it("title is correct", () => { expect(wrapper.find("h1").text()).toBe("Inventory Manager") }); it("input field loads correctly", () => { expect(wrapper.vm.$data.newitem).toBe("") }); it("add button works", async () => { // 绑定间谍到实际运行的实例方法上 const append = jest.spyOn(wrapper.vm, "appenditem"); // 给表单赋值,解除按钮禁用 wrapper.vm.newitem = "测试商品"; wrapper.vm.quantity = 5; // 等待响应式更新完成 await nextTick(); // 触发点击 wrapper.find(".submit").trigger("click"); await nextTick(); // 断言 expect(append).toHaveBeenCalled(); // 额外可以直接验证功能结果,更符合测试逻辑 // expect(wrapper.vm.array.length).toBe(1) }) })
内容的提问来源于stack exchange,提问作者Marecu
相关产品推荐
相关产品推荐

