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

如何为带有@Input属性的Angular 4 AllowOnlyNumbers指令编写单元测试?

没问题!针对你的Angular 4 AllowOnlyNumbers指令(带@Input开关),我整理了一套完整的单元测试方案,覆盖核心场景,直接就能用:

首先先补全指令的基础实现(基于你给出的开头,确保测试逻辑匹配):

import { Directive, HostListener, Input } from '@angular/core';

@Directive({
  selector: '[AllowOnlyNumbers]'
})
export class AllowOnlyNumbersDirective {
  @Input() AllowOnlyNumbers: boolean = true;

  @HostListener('keydown', ['$event'])
  onKeyDown(event: KeyboardEvent) {
    if (!this.AllowOnlyNumbers) return;

    // 允许基础控制键(用于编辑操作)
    const allowedControlKeys = [
      'Backspace', 'Tab', 'Enter', 'Escape', 'Delete',
      'ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown',
      'Home', 'End', 'PageUp', 'PageDown'
    ];

    // 允许主键盘数字和小键盘数字
    const isNumericKey = /^[0-9]$/.test(event.key) || /^NumPad[0-9]$/.test(event.key);
    
    if (allowedControlKeys.includes(event.key) || isNumericKey) {
      return;
    }

    // 阻止非允许的按键
    event.preventDefault();
  }
}

接下来是单元测试文件的编写,我们用Angular的TestBed来搭建测试环境,覆盖所有关键场景:

AllowOnlyNumbersDirective 单元测试

1. 测试环境配置

先创建一个测试组件用来挂载指令,然后配置TestBed:

import { Component, DebugElement } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { AllowOnlyNumbersDirective } from './allow-only-numbers.directive';

// 测试宿主组件,用来绑定指令和@Input属性
@Component({
  template: `<input [AllowOnlyNumbers]="isEnabled" type="tel" />`
})
class TestHostComponent {
  isEnabled: boolean = true;
}

describe('AllowOnlyNumbersDirective', () => {
  let fixture: ComponentFixture<TestHostComponent>;
  let inputElement: DebugElement;
  let hostComponent: TestHostComponent;

  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [AllowOnlyNumbersDirective, TestHostComponent]
    });

    fixture = TestBed.createComponent(TestHostComponent);
    hostComponent = fixture.componentInstance;
    inputElement = fixture.debugElement.query(By.css('input'));
    fixture.detectChanges();
  });

2. 核心测试用例

🔹 指令启用时,阻止非数字输入

验证字母、符号等非数字按键会被拦截:

it('should block non-numeric keys when directive is enabled', () => {
    const nonNumericKeys = ['a', '@', '#', '!', 'Z'];
    
    nonNumericKeys.forEach(key => {
      const keydownEvent = new KeyboardEvent('keydown', { key });
      spyOn(keydownEvent, 'preventDefault');

      inputElement.nativeElement.dispatchEvent(keydownEvent);
      expect(keydownEvent.preventDefault).toHaveBeenCalled();
    });
  });

🔹 指令启用时,允许数字键输入

验证主键盘的数字能正常输入:

it('should allow numeric keys when directive is enabled', () => {
    const numericKeys = ['0', '1', '5', '9'];
    
    numericKeys.forEach(key => {
      const keydownEvent = new KeyboardEvent('keydown', { key });
      spyOn(keydownEvent, 'preventDefault');

      inputElement.nativeElement.dispatchEvent(keydownEvent);
      expect(keydownEvent.preventDefault).not.toHaveBeenCalled();
    });
  });

🔹 指令启用时,允许控制键(退格、Tab等)

确保用户的编辑操作不受影响:

it('should allow control keys when directive is enabled', () => {
    const controlKeys = ['Backspace', 'Tab', 'ArrowLeft', 'Delete', 'Enter'];
    
    controlKeys.forEach(key => {
      const keydownEvent = new KeyboardEvent('keydown', { key });
      spyOn(keydownEvent, 'preventDefault');

      inputElement.nativeElement.dispatchEvent(keydownEvent);
      expect(keydownEvent.preventDefault).not.toHaveBeenCalled();
    });
  });

🔹 指令启用时,允许小键盘数字键

别忽略用户常用的小键盘输入场景:

it('should allow numpad numeric keys when directive is enabled', () => {
    const numpadKeys = ['NumPad0', 'NumPad3', 'NumPad9'];
    
    numpadKeys.forEach(key => {
      const keydownEvent = new KeyboardEvent('keydown', { key });
      spyOn(keydownEvent, 'preventDefault');

      inputElement.nativeElement.dispatchEvent(keydownEvent);
      expect(keydownEvent.preventDefault).not.toHaveBeenCalled();
    });
  });

🔹 指令禁用时,允许所有输入

验证@Input设为false时,指令完全失效:

it('should allow all keys when directive is disabled', () => {
    // 禁用指令
    hostComponent.isEnabled = false;
    fixture.detectChanges();

    const testKey = 'a';
    const keydownEvent = new KeyboardEvent('keydown', { key: testKey });
    spyOn(keydownEvent, 'preventDefault');

    inputElement.nativeElement.dispatchEvent(keydownEvent);
    expect(keydownEvent.preventDefault).not.toHaveBeenCalled();
  });

最后关闭describe块:

});

额外建议

如果你的指令还处理了粘贴事件(比如过滤粘贴内容中的非数字),可以添加对应的测试用例,模拟paste事件并验证输入框内容是否被正确过滤。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:48:16