Angular 2测试 - 提供RouteParams以路由到/ employees /:id / edit

时间:2016-04-18 09:42:55

标签: jasmine angular karma-runner angular2-routing

我有一个与路由/employees/:id/edit对应的组件。现在我想为它编写单元测试。

为此,我在RouteParams块中跟随beforeEachProviders

provide(RouteParams, { useValue: new RouteParams({ id: '1' }) }

我的猜测是id属性将被RouteParams mock替换。但是当我在it块中记录当前URL时,如:

console.log(window.location.href);

我得到LOG: 'http://localhost:9876/context.html'

此外,innerHtml为空。

那么,我应该以不同的方式模仿RouteParams吗?

组件代码:

import { Component, OnInit } from 'angular2/core';
import { RouteParams, Router } from 'angular2/router';

import { Employee } from '../models/employee';
import { EmployeeDetailServiceComponent } from '../services/employee-detail-service.component';
import { EmployeeEditFormServiceComponent } from '../services/employee-edit-form-service.component';

@Component({
  selector: 'employee-edit-form',
  template: `
    <div class="container">
    <h3>Employee Edit Form</h3>
    <form (ngSubmit)="onSubmit()" #employeeForm="ngForm" *ngIf="currentEmployee != undefined">
      <div class="form-group">
        <label for="name">Name</label>
       <input type="text" class="form-control" required [(ngModel)]="currentEmployee.name"
            ngControl="name"  #name="ngForm">
       <div [hidden]="name.valid || name.pristine" class="alert alert-danger">
         Name is required
       </div>
      </div>
      <button type="button" class="btn btn-default" (click)="editEmployee()" [disabled]="!employeeForm.form.valid">Update</button>
    </form>
  </div>
  `,
  providers: [
    EmployeeDetailServiceComponent,
    EmployeeEditFormServiceComponent
  ]
})

export class EmployeeEditFormComponent implements OnInit {
  public currentEmployee: Employee;
  public errorMessage: string;

  constructor(
    private _router: Router,
    private _routeParams: RouteParams,
    private _detailService: EmployeeDetailServiceComponent,
    private _editService: EmployeeEditFormServiceComponent
  ){}

  ngOnInit() {
    let id = parseInt(this._routeParams.get('id'));
    this._detailService.getEmployee(id).subscribe(
                     employee => this.currentEmployee = employee
                   );
  }

  editEmployee() {
    this._editService.editEmployee(this.currentEmployee)
    .subscribe(
      employee => this.currentEmployee = employee,
      error =>  this.errorMessage = <any>error,
      () => this._router.navigate(['EmployeeDetail', {id: this.currentEmployee.id}])
    );
  }
}

规范代码

/// <reference path="../../typings/main/ambient/jasmine/jasmine.d.ts" />

import {
    it,
    describe,
    expect,
    TestComponentBuilder,
    injectAsync,
    setBaseTestProviders,
    beforeEachProviders,
    resetBaseTestProviders
} from "angular2/testing";
import {
    Component,
    provide,
    ApplicationRef
} from "angular2/core";
import {
    TEST_BROWSER_PLATFORM_PROVIDERS,
    TEST_BROWSER_APPLICATION_PROVIDERS
} from "angular2/platform/testing/browser";
import {
    ROUTER_DIRECTIVES,
    ROUTER_PROVIDERS,
    ROUTER_PRIMARY_COMPONENT,
    APP_BASE_HREF,
    Router,
    RouteParams,
    RouteRegistry
} from 'angular2/router';
import {RootRouter} from "angular2/src/router/router";
import {SpyLocation} from "angular2/src/mock/location_mock";
import {Location} from "angular2/src/router/location/location";
import {
    XHRBackend,
    HTTP_PROVIDERS,
    Response,
    ResponseOptions
} from "angular2/http";
import { MockApplicationRef } from 'angular2/src/mock/mock_application_ref';
import {
    MockBackend,
    MockConnection
} from "angular2/src/http/backends/mock_backend";
import { BrowserDomAdapter } from 'angular2/src/platform/browser/browser_adapter';
import 'rxjs/Rx';

import { AppComponent } from '../app.component';
import { EmployeeEditFormComponent } from './employee-edit-form.component';
import { EmployeeDetailServiceComponent } from '../services/employee-detail-service.component';
import { EmployeeEditFormServiceComponent } from '../services/employee-edit-form-service.component';


class MockEmployeeDetailServiceComponent {}

class MockEmployeeEditFormServiceComponent {}


@Component({
    template: '<employee-edit-form></employee-edit-form>',
    directives: [EmployeeEditFormComponent]
})
class TestMyEditForm extends EmployeeEditFormComponent{}


describe('Employee Edit Form Tests', () => {
    resetBaseTestProviders();
    setBaseTestProviders(
        TEST_BROWSER_PLATFORM_PROVIDERS,
        TEST_BROWSER_APPLICATION_PROVIDERS
    );
    beforeEachProviders(() => {
        return [
            ROUTER_DIRECTIVES,
            ROUTER_PROVIDERS,
            HTTP_PROVIDERS,
            EmployeeEditFormComponent,
            EmployeeDetailServiceComponent,
            EmployeeEditFormServiceComponent,
            provide(XHRBackend, {useClass: MockBackend}),
            provide(APP_BASE_HREF, {useValue: '/'}),
            provide(ROUTER_PRIMARY_COMPONENT, {useValue: AppComponent}),
            provide(ApplicationRef, {useClass: MockApplicationRef}),
            RouteRegistry,
            provide(Location, {useClass: SpyLocation}),
            provide(Router, {useClass: RootRouter}),
            provide(RouteParams, { useValue: new RouteParams({ id: '1' }) })
        ]
    });

    it('Should display the edit form of employees',
        injectAsync([XHRBackend, TestComponentBuilder], (backend, tcb) => {
            backend.connections.subscribe(
                (connection:MockConnection) => {
                    var options = new ResponseOptions({
                        body: {
                            "id": 1,
                            "name": "Roshan Shrestha"
                        }
                    });

                    var response = new Response(options);

                    connection.mockRespond(response);
                }
            );

            return tcb
                .createAsync(TestMyEditForm)
                .then((fixture) => {
                    fixture.detectChanges();
                    var comp = fixture.debugElement.componentInstance;
                    console.log(comp);
                });
        })
    );
});

1 个答案:

答案 0 :(得分:0)

实际上,您提供的数据包含在注入parameters的{​​{1}}属性中。配置提供程序并将其指定到组件的构造函数中时,将注入实例,但不会更新URL,因为此处实际上没有涉及路由...

请参阅以下示例:

RouteParams

以下是相应的组件:

beforeEachProviders(() => {
  return [
    provide(RouteParams, { useValue: new RouteParams({ id: '1' })
  ];
});

it('should access route params', injectAsync([TestComponentBuilder], (tcb: TestComponentBuilder) => {
  return tcb.createAsync(DropdownComponent)
    .then(fixture => {
      let comp: DropdownComponent = fixture.componentInstance;
      fixture.detectChanges();

      expect(comp.data.params).toEqual({ id: '1' });
  });
}));

参见相应的plunkr:https://plnkr.co/edit/pFmiyk?p=preview