Angular 测试和 ngModel
Angular testing and ngModel
我正在用 Angular 编写我的第一个组件测试,但我在使 ngModel 绑定工作时遇到了一些困难。
这是我的测试模块定义:
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
LdapLoginComponent,
],
imports: [
CommonModule,
FormsModule,
NoopAnimationsModule,
MatInputModule,
MatFormFieldModule,
RouterTestingModule,
],
providers: [
{
provide: AuthorizationService,
useValue: { login() {} },
},
]
}).compileComponents();
}));
这是我的测试用例:
it('should bind form fields with class', fakeAsync(() => {
// Given
const username = 'username';
const password = 'password';
const usernameField = de.query(By.css('input[name=username]')).nativeElement;
const passwordField = de.query(By.css('input[name=password]')).nativeElement;
// When
usernameField.value = username;
passwordField.value = password;
usernameField.dispatchEvent(new Event('input'));
passwordField.dispatchEvent(new Event('input'));
tick();
fixture.detectChanges();
// Then
expect(comp.username).toEqual(username);
expect(comp.password).toEqual(password);
}));
我的组件class:
export class LdapLoginComponent {
username: string;
password: string;
errorMessage: string;
submitDisabled = false;
constructor(
private authorizationService: AuthorizationService,
private router: Router,
) {
}
login(): void {
delete this.errorMessage;
this.submitDisabled = true;
this.authorizationService.login(AuthorizationProvider.LDAP, this.username, this.password)
.subscribe(
() => {
this.router.navigate(['/']);
},
(err: Error) => {
this.errorMessage = err.message;
this.submitDisabled = false;
},
);
}
}
我的组件模板:
<form class="form-container" (submit)="login()">
<mat-form-field color="warn">
<input
matInput
type="text"
name="username"
placeholder="Insert your username"
[(ngModel)]="username"
required
i18n-placeholder="@@input.placeholder.username">
</mat-form-field>
<mat-form-field color="warn">
<input
matInput
type="password"
name="password"
placeholder="Insert your password"
[(ngModel)]="password"
required
i18n-placeholder="@@input.placeholder.password">
</mat-form-field>
<button
mat-raised-button
type="submit"
color="warn"
[disabled]="submitDisabled"
i18n="@@input.submit">Submit</button>
</form>
<article>{{errorMessage}}</article>
我正在更改测试中用户名和密码字段的值,我希望我的 class 的用户名和密码字段也相应更新。如果我在浏览器中手动测试一切正常,但在测试中却不行。
有什么想法吗?
谢谢。
问题是您实际上并没有在调用 dispatchEvent 之前设置输入字段的值。您正在直接设置组件属性。
comp.username = username;
usernameField.dispatchEvent(new Event('input'));
应该是
let usernameFieldElement = usernameField.nativeElement;
usernameFieldElement.value = username;
usernameField.dispatchEvent(new Event('input'));
密码也一样。
另一件事是您同时测试三件事,将文本输入到输入区域,单击按钮运行登录和登录功能本身。我建议将它们分成三个断言。
如上设置字段并检查数据绑定。
单击按钮并监视登录函数以检查它是否已被调用。
设置实际的组件属性并直接调用 logon() 并检查您的 navigateSpy 是否已正确调用。
这样,如果出现问题,您将能够更轻松地找到它。
看起来像垫输入字段,我们需要在更改输入之前执行 focus():
it('should bind form fields with class', fakeAsync(() => {
// Given
const username = 'username';
const password = 'password';
const usernameField = de.query(By.css('input[name=username]')).nativeElement;
const passwordField = de.query(By.css('input[name=password]')).nativeElement;
usernameField.focus();
passwordField.focus();
// When
usernameField.value = username;
passwordField.value = password;
usernameField.dispatchEvent(new Event('input'));
passwordField.dispatchEvent(new Event('input'));
tick();
fixture.detectChanges();
// Then
expect(comp.username).toEqual(username);
expect(comp.password).toEqual(password);
}));
我正在用 Angular 编写我的第一个组件测试,但我在使 ngModel 绑定工作时遇到了一些困难。 这是我的测试模块定义:
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
LdapLoginComponent,
],
imports: [
CommonModule,
FormsModule,
NoopAnimationsModule,
MatInputModule,
MatFormFieldModule,
RouterTestingModule,
],
providers: [
{
provide: AuthorizationService,
useValue: { login() {} },
},
]
}).compileComponents();
}));
这是我的测试用例:
it('should bind form fields with class', fakeAsync(() => {
// Given
const username = 'username';
const password = 'password';
const usernameField = de.query(By.css('input[name=username]')).nativeElement;
const passwordField = de.query(By.css('input[name=password]')).nativeElement;
// When
usernameField.value = username;
passwordField.value = password;
usernameField.dispatchEvent(new Event('input'));
passwordField.dispatchEvent(new Event('input'));
tick();
fixture.detectChanges();
// Then
expect(comp.username).toEqual(username);
expect(comp.password).toEqual(password);
}));
我的组件class:
export class LdapLoginComponent {
username: string;
password: string;
errorMessage: string;
submitDisabled = false;
constructor(
private authorizationService: AuthorizationService,
private router: Router,
) {
}
login(): void {
delete this.errorMessage;
this.submitDisabled = true;
this.authorizationService.login(AuthorizationProvider.LDAP, this.username, this.password)
.subscribe(
() => {
this.router.navigate(['/']);
},
(err: Error) => {
this.errorMessage = err.message;
this.submitDisabled = false;
},
);
}
}
我的组件模板:
<form class="form-container" (submit)="login()">
<mat-form-field color="warn">
<input
matInput
type="text"
name="username"
placeholder="Insert your username"
[(ngModel)]="username"
required
i18n-placeholder="@@input.placeholder.username">
</mat-form-field>
<mat-form-field color="warn">
<input
matInput
type="password"
name="password"
placeholder="Insert your password"
[(ngModel)]="password"
required
i18n-placeholder="@@input.placeholder.password">
</mat-form-field>
<button
mat-raised-button
type="submit"
color="warn"
[disabled]="submitDisabled"
i18n="@@input.submit">Submit</button>
</form>
<article>{{errorMessage}}</article>
我正在更改测试中用户名和密码字段的值,我希望我的 class 的用户名和密码字段也相应更新。如果我在浏览器中手动测试一切正常,但在测试中却不行。
有什么想法吗?
谢谢。
问题是您实际上并没有在调用 dispatchEvent 之前设置输入字段的值。您正在直接设置组件属性。
comp.username = username;
usernameField.dispatchEvent(new Event('input'));
应该是
let usernameFieldElement = usernameField.nativeElement;
usernameFieldElement.value = username;
usernameField.dispatchEvent(new Event('input'));
密码也一样。
另一件事是您同时测试三件事,将文本输入到输入区域,单击按钮运行登录和登录功能本身。我建议将它们分成三个断言。
如上设置字段并检查数据绑定。
单击按钮并监视登录函数以检查它是否已被调用。
设置实际的组件属性并直接调用 logon() 并检查您的 navigateSpy 是否已正确调用。
这样,如果出现问题,您将能够更轻松地找到它。
看起来像垫输入字段,我们需要在更改输入之前执行 focus():
it('should bind form fields with class', fakeAsync(() => {
// Given
const username = 'username';
const password = 'password';
const usernameField = de.query(By.css('input[name=username]')).nativeElement;
const passwordField = de.query(By.css('input[name=password]')).nativeElement;
usernameField.focus();
passwordField.focus();
// When
usernameField.value = username;
passwordField.value = password;
usernameField.dispatchEvent(new Event('input'));
passwordField.dispatchEvent(new Event('input'));
tick();
fixture.detectChanges();
// Then
expect(comp.username).toEqual(username);
expect(comp.password).toEqual(password);
}));