我正在尝试测试当我的模拟自定义异步验证器返回键值对时我的表单控件是否无效。
这是我创建的模拟验证器:
export async function mockUniqueEmailValidatorFn(control: AbstractControl) {
const existingEmailAddresses = ['[email protected]'];
if(existingEmailAddresses.includes(control.value)) {
return of({'emailUniquenessViolated': true})
.pipe(
first()
);
} else {
return of(null);
}
这是我设置的单元测试:
it('should be invalid when email has already been used to create an account', () => {
//Arrange
component.registerForm.controls['email'].clearAsyncValidators;
component.registerForm.controls['email'].addAsyncValidators(mockUniqueEmailValidatorFn);
//Act
component.registerForm.controls['email'].setValue("[email protected]");
fixture.detectChanges();
console.log(component.registerForm.controls['email']);
//Assert
expect(component.registerForm.controls['email'].invalid).toBeTruthy();
});
测试失败,因为电子邮件表单控件上的无效属性为 false。有什么想法为什么会发生这种情况吗?
我注意到了一些奇怪的事情。当我将控件记录到控制台时,表单控件既无效又不是无效:
此外,在将表单控件记录到控制台时,表单控件的状态为
"PENDING"
,即使我使用了 first()
rxjs 运算符,一旦它发出第一个值,它就应该完成可观察的操作:
我认为状态仍然是
PENDING
,因为我们可能需要使用fakeAsync/tick
。
尝试以下操作(注意!!):
// !! Add fakeAsync to the callback here.
it('should be invalid when email has already been used to create an account', fakeAsync(() => {
//Arrange
// !! You most likely need to call this method (add () to the end) component.registerForm.controls['email'].clearAsyncValidators();
component.registerForm.controls['email'].addAsyncValidators(mockUniqueEmailValidatorFn);
//Act
component.registerForm.controls['email'].setValue("[email protected]");
fixture.detectChanges();
// !! Call tick for the subscription to have completed and
// so you can start your assertions
tick();
console.log(component.registerForm.controls['email']);
//Assert
expect(component.registerForm.controls['email'].invalid).toBeTruthy();
}));
我偶然发现了类似的情况,状态卡在
PENDING
中,并且它将保持该状态,直到验证器返回的 Observable 完成。
您正在使用
of()
,理论上它直接完成了 Observable,但由于您在此之上使用了 .pipe(first())
,我的假设是这会创建另一个不再完成的 Observable。