我有一个与路由/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);
});
})
);
});
答案 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。