测试组件

测试准备

改造原先的Login组件,引入数据模型、inputs、outputs以及表单。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import {Component, EventEmitter, Input, Output} from '@angular/core';

export class User { 
  constructor(public email: string, public password: string) {
  }
}

@Component({
  selector: 'app-login',
  template: `
<form>
  <label>Email</label>
  <input type="email"
         #email>
  <label>Password</label>
  <input type="password"
         #password>
  <button type="button" 
          (click)="login(email.value, password.value)"
          [disabled]="!enabled">Login
  </button>
</form>
`
})
export class LoginComponent {
  @Output() loggedIn = new EventEmitter<User>(); 
  @Input() enabled = true; 

  login(email, password) { 
    console.log(`Login ${email} ${password}`);
    if (email && password) {
      console.log(`Emitting`);
      this.loggedIn.emit(new User(email, password));
    }
  }
}
  • 建立User类封装登录用户信息.
  • button按钮通过输入属性enabled控制是否显示,点击按钮将调用login方法
  • 组件将抛出loggedIn事件.

测试代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
describe('Component: Login', () => {

  let component: LoginComponent;
  let fixture: ComponentFixture<LoginComponent>;
  let submitEl: DebugElement;
  let loginEl: DebugElement;
  let passwordEl: DebugElement;

  beforeEach(() => {

    TestBed.configureTestingModule({
      declarations: [LoginComponent]
    });

    // create component and test fixture
    fixture = TestBed.createComponent(LoginComponent);

    // get test component from the fixture
    component = fixture.componentInstance;

    submitEl = fixture.debugElement.query(By.css('button'));
    loginEl = fixture.debugElement.query(By.css('input[type=email]'));
    passwordEl = fixture.debugElement.query(By.css('input[type=password]'));
  });
});

测试 @Inputs

为了测试Input,我们需要做到:

  • 能够改变组件的enabled输入值.
  • 能够验证按钮的可用状态与enabled值是一致的.
1
2
3
4
5
6
7
8
9
it('Setting enabled to false disables the submit button', () => {
  component.enabled = false;
});

it('Setting enabled to false disables the submit button', () => {
    component.enabled = false;
    fixture.detectChanges();
    expect(submitEl.nativeElement.disabled).toBeTruthy();
});

不要忘记调用detechChanges方法来更新view

测试 @Outputs

首先需要能够跟踪到组件抛出的事件

1
2
3
4
5
6
7
8
it('Entering email and password emits loggedIn event', () => {
  let user: User;

  component.loggedIn.subscribe((value) => user = value);

  expect(user.email).toBe("test@example.com");
  expect(user.password).toBe("123456");
});

关键点是 component.loggedIn.subscribe((value) => user = value);

output事件实际上是一个Observable对象,因此我们可以订阅它。每次变化时订阅者都将获得通知。 随后可以对获得的user对象进行断言判断

那如何触发这个事件呢?当然我们可以调用component.login方法,但是我们更希望能够从view上触发这个方法。

首先我们给email与password输入框赋值

loginEl.nativeElement.value = "test@example.com";
passwordEl.nativeElement.value = "123456";

然后通过submit按钮触发事件,并且需要在订阅完成之后再执行。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
it('Entering email and password emits loggedIn event', () => {
  let user: User;
  loginEl.nativeElement.value = "test@example.com";
  passwordEl.nativeElement.value = "123456";

  component.loggedIn.subscribe((value) => user = value);

  submitEl.triggerEventHandler('click', null);

  expect(user.email).toBe("test@example.com");
  expect(user.password).toBe("123456");
});