Angular 4监听键盘事件的组件单元测试失败,原因何在?
Angular单元测试中键盘事件未触发计数器变化的原因与解决办法
你遇到这个测试失败的问题,其实有两个关键原因,咱们一个个拆解:
1. 枚举定义和实际使用不匹配
你看你定义的KEY_CODE枚举里只有RIGHT_ARROW和LEFT_ARROW,但组件的事件处理代码里却在判断KEY_CODE.UP_ARROW和KEY_CODE.DOWN_ARROW——这两个枚举值根本不存在啊!就算事件触发了,条件判断也不会走进去,counter自然不会变化。
先把枚举修复成正确的:
export enum KEY_CODE { UP_ARROW = 38, // 上箭头的keyCode是38 DOWN_ARROW = 40 // 下箭头的keyCode是40 };
2. 事件触发的目标不对
你的@HostListener监听的是window对象的keyup事件,但测试代码里用fixture.debugElement.triggerEventHandler('keyup', upKeyPress)触发的是组件根元素的keyup事件,这俩不是同一个事件源,组件里的handleKeypress方法根本没被调用到。
针对这个问题,有两种靠谱的解决办法:
方法一:直接调用组件的事件处理方法(简单高效)
单元测试的核心是验证逻辑,咱们可以跳过事件触发的环节,直接调用组件的handleKeypress方法,传入模拟的键盘事件就行:
it('should increment when you push the "up" key', () => { const fixture = TestBed.createComponent(AppComponent); const app = fixture.componentInstance; expect(app.counter).toBe(0); // 直接调用事件处理方法,传入模拟事件 app.handleKeypress({ keyCode: KEY_CODE.UP_ARROW } as KeyboardEvent); expect(app.counter).toBe(1); });
方法二:模拟window上的keyup事件(贴近真实场景)
如果想更贴近真实浏览器的行为,咱们可以直接给window对象触发keyup事件:
it('should increment when you push the "up" key', () => { const fixture = TestBed.createComponent(AppComponent); const app = fixture.componentInstance; expect(app.counter).toBe(0); // 创建标准的KeyboardEvent并触发window上的keyup const upEvent = new KeyboardEvent('keyup', { keyCode: KEY_CODE.UP_ARROW }); window.dispatchEvent(upEvent); // 别忘了触发变更检测,让Angular感知到组件状态变化 fixture.detectChanges(); expect(app.counter).toBe(1); });
注意哈,第二种方法里必须调用fixture.detectChanges(),因为window事件是异步触发的,Angular不会自动检测到组件的状态更新,手动调用变更检测才能让断言生效。
内容的提问来源于stack exchange,提问作者Stewart
相关产品推荐
相关产品推荐

