JoW*_*ter 6 components unit-testing jasmine angular
我正在尝试测试使用服务的Angular 2组件.该服务注入了Http,我对测试不感兴趣所以我试图模拟服务并监视服务的方法调用.这是我在Angular 1中非常熟悉的事情,但我无法在Angular 2中工作.我得到的错误是Http的无提供者!我有兴趣监视实际的服务方法,而不是嘲笑它.
我的组件看起来像这样:
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();
}
}
Run Code Online (Sandbox Code Playgroud)
我的服务看起来像这样:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
最后我的测试看起来像这样
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([]));
}
Run Code Online (Sandbox Code Playgroud)
感谢大家的帮助,让我看到了正确的区域.缺少的是导入HttpModule.非常感谢艾哈迈德的建议.这是我的固定测试供参考:
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([]));
}
Run Code Online (Sandbox Code Playgroud)
不需要模拟对象或任何东西,完美
正是因为这个
@Component({
providers: [NavBarService], <==== !!!!!
})
export class NavBarComponent {
Run Code Online (Sandbox Code Playgroud)
优先@Component.providers于提供的任何内容和模块级别。因此 Angular 将尝试创建 的实例,NavBarService而不是使用您在测试中配置的模拟。
Angular 允许我们覆盖@Component.providers以及其他类似的东西@Component.template。我们可以通过以下方式做到这一点
TestBed.configureTestingModule({
declarations: [NavBarComponent]
})
.overrideComponent(NavBarComponent, {
set: {
providers: [
{ provide: NavBarService, useClass: MockNavBarService}
]
}
})
.compileComponents()
.then(createComponent)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3812 次 |
| 最近记录: |