次のコードのリストコンポーネントがあります。
///<reference path="../../node_modules/angular2/typings/browser.d.ts"/>
import { Component, OnInit } from 'angular2/core';
import { ROUTER_DIRECTIVES } from 'angular2/router';
import { Employee } from '../models/employee';
import { EmployeeListServiceComponent } from '../services/employee-list-service.component';
@Component({
selector: 'employee-list',
template: `
<ul class="employees">
<li *ngFor="#employee of employees">
<a [routerLink]="['EmployeeDetail', {id: employee.id}]">
<span class="badge">{{employee.id}}</span>
{{employee.name}}
</a>
</li>
</ul>
`,
directives: [ROUTER_DIRECTIVES],
providers: [EmployeeListServiceComponent]
})
export class EmployeeListComponent implements OnInit {
public employees: Employee[];
public errorMessage: string;
constructor(
private _listingService: EmployeeListServiceComponent
){}
ngOnInit() {
this._listingService.getEmployees().subscribe(
employees => this.employees = employees,
error => this.errorMessage = <any>error
);
}
}
ngOninit
フックの単体テストを作成したいと思います。私は次のテストを書きました:
/// <reference path="../../typings/main/ambient/jasmine/jasmine.d.ts" />
import {
it,
describe,
expect,
TestComponentBuilder,
injectAsync,
setBaseTestProviders,
beforeEachProviders,
} from "angular2/testing";
import { Component, provide, ApplicationRef, OnInit } 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
} from 'angular2/router';
import {XHRBackend, HTTP_PROVIDERS} from "angular2/http";
import { MockApplicationRef } from 'angular2/src/mock/mock_application_ref';
import {MockBackend } from "angular2/src/http/backends/mock_backend";
import {Observable} from 'rxjs/Rx';
import 'rxjs/Rx';
import { Employee } from '../models/employee';
import { EmployeeListComponent } from './list.component';
import { EmployeeListServiceComponent } from '../services/employee-list-service.component';
class MockEmployeeListServiceComponent {
getEmployees () {
return Observable.of([
{
"id": 1,
"name": "Abhinav Mishra"
}
]);
}
}
@Component({
template: '<employee-list></employee-list>',
directives: [EmployeeListComponent],
providers: [MockEmployeeListServiceComponent]
})
class TestMyList {}
describe('Employee List Tests', () => {
setBaseTestProviders(TEST_BROWSER_PLATFORM_PROVIDERS, TEST_BROWSER_APPLICATION_PROVIDERS);
beforeEachProviders(() => {
return [
ROUTER_DIRECTIVES,
ROUTER_PROVIDERS,
HTTP_PROVIDERS,
provide(EmployeeListServiceComponent, {useClass: MockEmployeeListServiceComponent}),
provide(XHRBackend, {useClass: MockBackend}),
provide(APP_BASE_HREF, {useValue: '/'}),
provide(ROUTER_PRIMARY_COMPONENT, {useValue: EmployeeListComponent}),
provide(ApplicationRef, {useClass: MockApplicationRef})
]
});
it('Should be true',
injectAsync([TestComponentBuilder], (tcb) => {
return tcb
.createAsync(TestMyList)
.then((fixture) => {
fixture.detectChanges();
var compiled = fixture.debugElement.nativeElement;
console.log(compiled.innerHTML);
expect(true).toBe(true);
});
})
);
});
ただし、テストでのconsole.log
の出力は、次のように空のul
タグです。
'<employee-list>
<ul class="employees">
<!--template bindings={}-->
</ul>
</employee-list>'
コンポーネントフックのユニットテストを書く適切な方法を誰かが私に提案できますか?
[〜#〜]ソリューション[〜#〜]
次のように、injectAsync
ブロックのhttpリクエストをモックします。
backend.connections.subscribe(
(connection:MockConnection) => {
var options = new ResponseOptions({
body: [
{
"id": 1,
"name": "Abhinav Mishra"
}
]
});
var response = new Response(options);
connection.mockRespond(response);
}
);
しかし今、私は次のような別のエラーが発生しています:
Failed: EXCEPTION: Component "EmployeeListComponent" has no route config. in [['EmployeeDetail', {id: employee.id}] in EmployeeListComponent@3:7]
ORIGINAL EXCEPTION: Component "EmployeeListComponent" has no route config.
ORIGINAL STACKTRACE:
Error: Component "EmployeeListComponent" has no route config.
ngOnInit()
で非同期コードを呼び出す場合、console.log(...)
が実行されたときに非同期コードが完了したとは限りません。 _this.employees
_は、応答が到着した後にsubscribe(...)
に渡したコールバックが呼び出された場合にのみ設定されます。
MockBackend を使用すると、応答を制御でき、応答が渡された後、fixture.detectChanges()
を再度実行して、更新されたデータでコンポーネントを再レンダリングする必要があります。 innerHTML
そして、レンダリングされたコンテンツが含まれていることを期待します。