麻烦单元测试角度的反应性表单字段
Posted
技术标签:
【中文标题】麻烦单元测试角度的反应性表单字段【英文标题】:trouble unit testing reactive form fields in angular 【发布时间】:2017-06-27 21:11:04 【问题描述】:我正在学习 Angular 2 和使用 @angular/cli 1.0.0-beta.30 进行单元测试,并在测试表单字段有效性的一个方面取得了一些成功,但不是全部。我暂时在我的组件中使用内联模板来消除一层复杂性(单独文件中的表单模板引入了异步性,对吗?)。
ngOnInit()
定义了一个 name
属性,其中包括“required”和“minLength”的验证器。目前,一个空的表单域将正确触发“required”验证器,但不会触发“minLength”验证器。测试中的name.errors
数组根本不包含任何对required的引用,name.errors['minLength']
返回undefined
。 minLength 是否需要异步处理?我无法找到适合我的问题的文档或示例。
// signup-form.component.ts
...
export class SignupFormComponent implements OnInit
user: FormGroup;
constructor(private fb: FormBuilder)
ngOnInit()
this.user = this.fb.group(
name: ['', [Validators.required, Validators.minLength(2)]],
account: this.fb.group(
email: ['', Validators.required, Validators.pattern("[^ @]*@[^ @]*")],
confirm: ['', Validators.required]
)
)
onSubmit( value, valid : value: User, valid: boolean )
console.log(value, valid);
我的测试
// signup-form.component.spec.ts
import SignupFormComponent from './signup-form.component';
describe('SignupFormComponent', () =>
let component: SignupFormComponent;
let fixture: ComponentFixture<SignupFormComponent>;
beforeEach(async(() =>
TestBed.configureTestingModule(
declarations: [SignupFormComponent],
imports: [
ReactiveFormsModule,
FormsModule
]
)
.compileComponents();
));
beforeEach(() =>
fixture = TestBed.createComponent(SignupFormComponent);
component = fixture.componentInstance;
component.ngOnInit();
fixture.detectChanges();
);
it('should create', () =>
expect(component).toBeTruthy();
);
it('form invalid when empty', () =>
expect(component.user.valid).toBeFalsy();
);
it('name field validity', () =>
let name = component.user.controls['name'];
expect(name.valid).toBeFalsy();
let errors = ;
name.setValue("");
errors = name.errors || ;
expect(errors['required']).toBeTruthy(); // this works
expect(errors['minLength']).toBeTruthy(); // this fails, "undefined"
);
);
【问题讨论】:
【参考方案1】:回答你的问题
name.errors['minLength'] 返回 undefined,minLength 是否需要 异步处理?
您可以只检查表单中的特定错误
expect(form.control.hasError('emailInvalid', ['email'])).toBe(true);
下面是完整的测试
// signup-form.component.spec.ts
import SignupFormComponent from './signup-form.component';
describe('SignupFormComponent', () =>
let component: SignupFormComponent;
let fixture: ComponentFixture<SignupFormComponent>;
beforeEach(async(() =>
TestBed.configureTestingModule(
declarations: [SignupFormComponent],
imports: [
ReactiveFormsModule,
FormsModule
]
)
.compileComponents();
));
beforeEach(() =>
fixture = TestBed.createComponent(SignupFormComponent);
component = fixture.componentInstance;
component.ngOnInit();
fixture.detectChanges();
);
it('should create', () =>
expect(component).toBeTruthy();
);
it('form invalid when empty', () =>
expect(component.user.valid).toBeFalsy();
);
it('name field validity', () =>
let name = component.user.controls['name'];
expect(name.valid).toBeFalsy();
name.setValue("");
expect(name.hasError('required')).toBeTruthy();
name.setValue("A");
expect(name.hasError('minLength')).toBeTruthy();
);
);
【讨论】:
【参考方案2】:expect(name.hasError('minlength', ['minlength'])).toEqual(false);
试试这个对我有用
【讨论】:
【参考方案3】:我相信这是因为您要查找的验证密钥是“minlength”非驼峰式,请注意小写“l”。我个人遇到过这个名字奇怪的错误属性。
【讨论】:
【参考方案4】:'minLength' 的处理方式与“required”或任何其他验证器(例如 maxLength、模式)相同。
除非您的 signup-form.component.ts 代码被截断,否则我相信您遗漏了一些东西。
在您的 FormBuilder 中,您需要订阅数据更改。
this.user.valueChanges.subscribe(data => this.onValueChanged(data));
然后你需要声明 onValueChanged 函数。请参阅 Angular Form Validation cookbook 了解通用 onValueChanged 函数。
您还需要使用适当的键填充 formErrors 对象。
formErrors =
'name': ''
并提供验证消息。
validationMessages =
'name':
'required': 'Name is required.',
'minlength': 'Name must be at least 2 characters long.'
【讨论】:
【参考方案5】:这是由于 Validator.required 优先级,当此类错误存在时 - 甚至没有调用其他验证器并且不会产生其他错误。您需要设置一些不正确的值来测试该特定部分:)
【讨论】:
【参考方案6】:expect(errors['minlength']).toBeTruthy();
【讨论】:
以上是关于麻烦单元测试角度的反应性表单字段的主要内容,如果未能解决你的问题,请参考以下文章
如何对 ngControl 用 @Self 装饰的反应性组件进行单元测试
如何使用 EntityType 字段对 Symfony 4 表单进行单元测试