如何修正Vue单元测试以正确测试含DOM操作的close方法?
修正Vue单元测试的方案
你的close方法通过判断事件触发元素是否在#target节点内,来决定是否隐藏组件。当前测试直接调用close()时,因为没有传入event参数,event?.target为undefined,element值为false,所以会触发isVisible = false,这个测试逻辑本身是成立的。但如果要完整覆盖两种场景,或者更严谨地模拟真实DOM交互,可以按以下方式修改测试:
场景1:点击非目标区域(或无事件对象),隐藏组件
it('should hide visibility when clicking outside #target', () => { const wrapper = shallowMount(AccountLogin, { mocks }) // 模拟一个不包含#target的事件对象 const mockEvent = { target: { closest: jest.fn().mockReturnValue(null) } } wrapper.vm.close(mockEvent) expect(wrapper.vm.$data.isVisible).toBe(false) // 验证closest方法被正确调用 expect(mockEvent.target.closest).toHaveBeenCalledWith('#target') })
场景2:点击#target内部元素,不隐藏组件
it('should not hide visibility when clicking inside #target', () => { const wrapper = shallowMount(AccountLogin, { mocks }) // 先设置isVisible为true,方便验证 wrapper.vm.$data.isVisible = true // 模拟一个包含#target的事件对象 const mockTarget = document.createElement('div') const mockEvent = { target: mockTarget } // 让closest返回自身,模拟在#target内 jest.spyOn(mockTarget, 'closest').mockReturnValue(mockTarget) wrapper.vm.close(mockEvent) expect(wrapper.vm.$data.isVisible).toBe(true) expect(mockTarget.closest).toHaveBeenCalledWith('#target') })
补充说明
- 用Jest的
jest.fn()来模拟closest方法的返回值,无需真实渲染DOM节点,避免直接操作真实DOM的开销。 - 如果确实需要直接操作DOM(比如模拟真实的DOM结构),也可以在测试中创建真实的DOM元素并挂载:
it('should hide visibility when clicking outside real #target', () => { const wrapper = shallowMount(AccountLogin, { mocks }) // 创建真实的#target元素并添加到文档 const targetElement = document.createElement('div') targetElement.id = 'target' document.body.appendChild(targetElement) // 模拟点击#target外的元素 const outsideElement = document.createElement('div') document.body.appendChild(outsideElement) const mockEvent = { target: outsideElement } wrapper.vm.close(mockEvent) expect(wrapper.vm.$data.isVisible).toBe(false) // 测试后清理DOM document.body.removeChild(targetElement) document.body.removeChild(outsideElement) })
内容的提问来源于stack exchange,提问作者Pianoc
相关产品推荐
相关产品推荐

