Angular 4单元测试表

时间:2017-05-13 04:25:30

标签: angular unit-testing

我试图填写Angular 4中的表单并测试结果。这是组件:

import { Component } from '@angular/core';
import { Validators, FormBuilder, FormGroup } from '@angular/forms';
import { NavController, NavParams } from 'ionic-angular';
import { Angular2TokenService } from 'angular2-token';

@Component({
  selector: 'page-create-account',
  templateUrl: 'create_account.html'
})
export class CreateAccountPage {
  private account : FormGroup;
  selectedItem: any;
  icons: string[];
  items: Array<{title: string, note: string, icon: string}>;

  constructor(public navCtrl: NavController, public navParams: NavParams, private formBuilder: FormBuilder, private _tokenService: Angular2TokenService) {
    this.account = this.formBuilder.group({
      first_name: ['', Validators.required],
      last_name: ['', Validators.required],
      email: ['', Validators.required],
      password: ['', [Validators.required, Validators.minLength(8)]],
      passwordConfirmation: [''],
    });
  }

  createAccount() {
    this.account.value['passwordConfirmation'] = this.account.value['password'];
    this._tokenService.registerAccount(this.account.value).subscribe(
        res =>      this.navCtrl.push(StartListingPage),
        error =>    console.log(error)
    );
  }

  login(event) {
    this.navCtrl.setRoot(LoginAccountPage);
  }
}

这是我的模板:

<ion-header>
  <ion-navbar>
    <button ion-button menuToggle>
      <ion-icon name="menu"></ion-icon>
    </button>
    <ion-title>Create Account</ion-title>
  </ion-navbar>
</ion-header>

<ion-content>
  <form [formGroup]="account" (ngSubmit)="createAccount()">
    <ion-list>
      <ion-item>
        <ion-label floating>First Name</ion-label>
        <ion-input type="text" formControlName="first_name"></ion-input>
      </ion-item>

      <ion-item>
        <ion-label floating>Last Name</ion-label>
        <ion-input type="text" formControlName="last_name"></ion-input>
      </ion-item>

      <ion-item>
        <ion-label floating>Email</ion-label>
        <ion-input type="text" formControlName="email"></ion-input>
      </ion-item>

      <ion-item>
        <ion-label floating>Password</ion-label>
        <ion-input type="password" formControlName="password"></ion-input>
      </ion-item>
    </ion-list>

    <div style="width:90%; margin: 0px auto; text-align:center;">
      <button ion-button block type="submit" [disabled]="!account.valid">Create Account</button>
      <div style="margin-top:20px;"><a (click)="login()">Already Have an Account? Login!</a></div>
    </div>
  </form>
</ion-content>

所以我创建了以下规范:

import { Nav, Platform } from 'ionic-angular';
import { StatusBar } from '@ionic-native/status-bar';
import { SplashScreen } from '@ionic-native/splash-screen';
import { Angular2TokenService } from 'angular2-token';
import { TestBed, getTestBed, ComponentFixture, async } from '@angular/core/testing';
import { IonicModule } from 'ionic-angular';
import { By }              from '@angular/platform-browser';
import { DebugElement }    from '@angular/core';
import { Validators, FormBuilder, FormGroup } from '@angular/forms';
import { NavController, NavParams } from 'ionic-angular';
import { CreateAccountPage } from './create_account';

let comp: CreateAccountPage;
let fixture: ComponentFixture<CreateAccountPage>;

class MockNavParams {
  data = { };
}

describe('CreateAccountPage', () => {
    beforeEach(async(() => {
        let tokenMock = jasmine.createSpyObj('tokenMock', ['registerAccount', 'subscribe']);
        tokenMock.registerAccount.and.returnValue(tokenMock);
        TestBed.configureTestingModule({
            declarations: [ CreateAccountPage ],
            providers: [ NavController, FormBuilder,
                { provide: Angular2TokenService, useValue: tokenMock },
                { provide: NavParams, useClass: MockNavParams},
            ],
            imports: [
                IonicModule.forRoot(CreateAccountPage)
            ],
        }).compileComponents();
    }));

    beforeEach(() => {
        fixture = TestBed.createComponent(CreateAccountPage);
        comp    = fixture.componentInstance;
    });

    afterEach(() => {
        fixture.destroy();
        comp = null;
    });

    it('should create account when clicked', () => {    
        fixture.detectChanges();
        let inputs = fixture.debugElement.queryAll(By.css('input'));

        let first = inputs[0].nativeElement;
        first.value = 'Jason';
        first.dispatchEvent(new Event('input'));
        expect(comp.account.value['first_name']).toBe('Jason');

        let form = fixture.debugElement.query(By.css('form'));
        form.triggerEventHandler('submit', null);
        // The above works or this line also works:
        //form.nativeElement.dispatchEvent(new Event('submit'));
        expect(comp.createAccount).toHaveBeenCalled;

        let tokenMock = getTestBed().get(Angular2TokenService);
        expect(tokenMock.registerAccount).toHaveBeenCalledWith({
            first_name: 'Jason',
            last_name: '',
            email: '',
            password: '',
            passwordConfirmation: ''
        });
    });
});

我的测试结果表明registerAccount被调用,但所有字段都是空白的。所以我觉得我很接近,但我无法弄清楚如何填写表格。有什么想法吗?

编辑:我发现在线代码似乎表明我需要将事件发送到Angular系统,所以我添加了但仍然没有骰子。

成功:我之前在By.css选择中抓取了错误的元素。我将上面的示例更新为我的工作解决方案。

1 个答案:

答案 0 :(得分:0)

我将上述规范更新为我的工作解决方案。主要问题是我没有调用first.dispatchEvent(new Event('input'));我的By.css行中也有一个糟糕的CSS选择。