I am trying to test an Angular 2 component that uses a service. The service has Http injected into it, which I am not interested in testing so I am trying to mock the service and spy on the service's method call. This is something I was quite familiar with doing in Angular 1 but I just can't get to work in Angular 2. The error I'm getting is No provider for Http! I am interested in spying on the actual services method rather than mocking it out.
My component looks like this:
import { Component, OnInit } from '@angular/core';
import { NavBarLink } from '../../models/nav-bar-link';
import { NavBarService } from '../../services/nav-bar/nav-bar.service';
@Component({
selector: 'nav-bar',
providers: [NavBarService],
moduleId: module.id,
templateUrl: 'nav-bar.template.html'
})
export class NavBarComponent {
constructor(private _navBarService: NavBarService) { }
links: NavBarLink[];
getLinks(): void {
this._navBarService.getNavBarLinks().then(data => this.links = data);
}
ngOnInit(): void {
this.getLinks();
}
}
And my service looks like this:
import { Injectable } from '@angular/core';
import { Headers, Http } from '@angular/http';
import 'rxjs/add/operator/toPromise';
import { Urls } from '../../constants/urls.constants';
import { NavBarLink } from '../../models/nav-bar-link';
@Injectable()
export class NavBarService {
constructor(private _http: Http,
private _urls: Urls) { }
getNavBarLinks():Promise<NavBarLink[]> {
return this._http.get(this._urls.NAV_BAR_LINKS)
.toPromise()
.then(response => {
let navLinks = [];
for(let navLink of response.json()) {
navLinks.push(new NavBarLink(navLink.id, navLink.description, navLink.route));
}
return navLinks;
})
.catch(this.handleError);
}
private handleError(error: any): Promise<any> {
console.error('An error occurred', error); // for demo purposes only
return Promise.reject(error.message || error);
}
}
And finally my test looks like this
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { Provider } from '@angular/core';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';
import { NavBarComponent } from './nav-bar.component';
import { NavBarService } from '../../services/nav-bar/nav-bar.service';
import { Observable } from 'rxjs/Rx';
let comp: NavBarComponent;
let fixture: ComponentFixture<NavBarComponent>;
let navBarService;
class MockNavBarService extends NavBarService{
constructor() {
super(null, null);
}
}
describe ('NavBarComponent tests', () => {
beforeEach( async(() => {
TestBed.configureTestingModule({
declarations: [ NavBarComponent ],
providers: [ {provide: NavBarService, useClass: MockNavBarService} ]
})
.compileComponents()
.then(createComponent);
}));
it('should call the getNavBarLinks when ngOnInit is called', () => {
comp.ngOnInit();
expect(navBarService.getNavBarLinks).toHaveBeenCalled();
});
});
function createComponent() {
fixture = TestBed.createComponent(NavBarComponent);
comp = fixture.componentInstance;
navBarService = fixture.debugElement.injector.get(NavBarService);
spyOn(navBarService, 'getNavBarLinks').and.returnValue(Promise.resolve([]));
}
Thanks for your help everyone, it got me looking in the right area. What was missing was importing HttpModule. Big thanks to the Ahmed for suggesting this. Here is my fixed test for reference:
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { Provider } from '@angular/core';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';
import { HttpModule } from '@angular/http'; // <==== IMPORT THIS
import { MockBackend } from '@angular/http/testing';
import { NavBarComponent } from './nav-bar.component';
import { NavBarService } from '../../services/nav-bar/nav-bar.service';
import { Urls } from '../../constants/urls.constants';
import { Observable } from 'rxjs/Rx';
let comp: NavBarComponent;
let fixture: ComponentFixture<NavBarComponent>;
var navBarService;
describe ('NavBarComponent tests', () => {
beforeEach( async(() => {
TestBed.configureTestingModule({
declarations: [ NavBarComponent ],
imports: [ HttpModule], //<==IMPORT INTO TEST BED
providers: [
Urls,
MockBackend,
NavBarService ]
})
.compileComponents()
.then(createComponent);
}));
it('should call the getNavBarLinks when ngOnInit is called', () => {
comp.ngOnInit();
expect(navBarService.getNavBarLinks).toHaveBeenCalled();
});
});
function createComponent() {
fixture = TestBed.createComponent(NavBarComponent);
comp = fixture.componentInstance;
navBarService = fixture.debugElement.injector.get(NavBarService);
spyOn(navBarService, 'getNavBarLinks').and.returnValue(Promise.resolve([]));
}
No need for mock objects or anything, perfect
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