I have a listing component with following code:
///<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
);
}
}
I wish to write unit tests for the ngOninit
hook. I have written following test:
/// <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);
});
})
);
});
However, the output of console.log
in the test is an empty ul
tag as follows:
'<employee-list>
<ul class="employees">
<!--template bindings={}-->
</ul>
</employee-list>'
Can anyone suggest me the proper way of writing unit tests for component hooks?
SOLUTION
Mock the http request in the injectAsync
block as follows:
backend.connections.subscribe(
(connection:MockConnection) => {
var options = new ResponseOptions({
body: [
{
"id": 1,
"name": "Abhinav Mishra"
}
]
});
var response = new Response(options);
connection.mockRespond(response);
}
);
However now i am getting another error as follows:
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.
If you call async code in ngOnInit()
you can't assume it is completed when console.log(...)
is executed. this.employees
is only set when the callback you passed to subscribe(...)
gets called after the response arrived.
If you use MockBackend you can control the response and after the response was passed you have to run fixture.detectChanges()
again to make the component re-render with the updated data, then you can read innerHTML
and expect it to contain the rendered content.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With