用于角度定制验证的单元测试

时间:2020-01-15 12:00:54

标签: angular typescript unit-testing karma-runner

请帮助测试自定义验证器。 尝试解决此问题的两个星期没有任何反应。

以html

<div>
<input type="text" class="value-input"  [(ngModel)]="element.value" name = "RegisterValue" #ValueReg = "ngModel"  [viewRegister] = 'viewChoiceDispleyReg' [viewType] = 'displeyView' valueName>
</div>

指令

import { AbstractControl, ValidatorFn, FormControl } from '@angular/forms';
import { Directive, ElementRef, Input } from '@angular/core';
import { NG_VALIDATORS, Validator } from '@angular/forms';

@Directive({
    selector: '[valueName]',
    providers: [
        { provide: NG_VALIDATORS, useExisting: valueValidator, multi: true }
      ]
  })
  export class valueValidator implements Validator{

  validator: ValidatorFn;
  @Input('viewType') viewType;
  @Input('viewRegister') viewRegister;

  constructor(private elementRef: ElementRef) {
    this.validator = this.validateValueFactory();
  }

  validate(c: FormControl) {
    return this.validator(c);
  }

  // validation function
  validateValueFactory() : ValidatorFn {
    return (c: AbstractControl) => {
      console.log("validate: " + c.value + ", view type: " + this.viewType);
      let isValid = c.value === '0';

      if(isValid) {
          return null;
      } else {
          return {
              valueName: {
                  valid: false
              }
          };
        }
    }
  } 
}

我在其他站点上研究了很多关于stackoverflow的材料。主要问题是我不知道如何创建用于测试验证程序的组件。在此测试中,组件将为属性(@ viewType,@ viewRegister)添加所需的验证器。 如何为此验证程序编写单元测试?

2 个答案:

答案 0 :(得分:1)

Here是测试指令的有用指南。

总结:

  1. 在测试中创建一个虚拟组件
  2. 为该虚拟组件提供HTML
  3. 确保在测试平台模块设置中声明虚拟组件和指令
  4. 写下您的断言。

类似...

import {valueValidator } from '[pathToValidator]';
@Component({
  template: `
    <div>
        <input type="text" class="value-input"  [(ngModel)]="element.value" name = "RegisterValue" #ValueReg = "ngModel"  [viewRegister] = 'viewChoiceDispleyReg' [viewType] = 'displeyView' valueName>
    </div>
    `
})
class DummyComponent {}

describe('valueValidator ', () => {

    let component: DummyComponent;
    let fixture: ComponentFixture<DummyComponent>;

  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [
        DummyComponent,
        valueValidator
      ]
    }).compileComponents();

    fixture = TestBed.createComponent(DummyComponent);
    component = fixture.componentInstance;
  });


  it('should create an instance', () => {
    expect(component).toBeTruthy();
    // insert additional assertions here.
  });
});

答案 1 :(得分:0)

碰巧的是,我花了很多时间写什么测试。我留下的意见是为了促进解决方案的发现。让我提醒您,如果输入的数字不为0,则定制验证器会出错。 1)创建测试组件

@Component({
  template: `
    <form>
    <input type="text" class="value-input" [(ngModel)]="element" name="register" #ValueReg = "ngModel"  
    [viewRegister] = 'viewChoiceDispleyReg' [viewType] = 'displeyView' valueName>
    </form>
  `
})class TestComponent {
  public element: string = '1';
  public viewRegister: string = Constant.DISPLEY_VIEW[0];
  public viewType: string = Constant.DISPLEY_VIEW[1];
}

2)初始测试

describe('Custom validation valueValidator', () => {
  let component: TestComponent;
  let fixture: ComponentFixture<TestComponent>;
  beforeEach(() => {
      TestBed.configureTestingModule({
        declarations: [
          TestComponent,
          valueValidator,
        ],
        imports: [
          BrowserModule,
          FormsModule
        ],
      }).compileComponents();

    fixture = TestBed.createComponent(TestComponent);
    component = fixture.componentInstance;
  });
});

3)编写测试

it('set value 2 get error', () => {
    fixture.detectChanges();

    fixture.whenStable().then(() => {

      let comp = fixture.componentInstance;
      let debug = fixture.debugElement;
      let input = debug.query(By.css('[name=register]'));
      let inputElement = input.nativeElement;

      inputElement.value = '2';//set intresting value
      inputElement.dispatchEvent(new Event('input'));//load value to input 

      let form: NgForm = fixture.debugElement.children[0].injector.get(NgForm);
      let control = form.control.get('register');
      expect(control.valid).toBe(false);
    })
  });