2016-10-29 138 views
11

我正在尝试为我的服务中使用的组件编写单元测试。 组件和服务正常工作。在单元测试期间在angular2中模拟定制服务

组件:

import {Component} from '@angular/core'; 
import {PonyService} from '../../services'; 
import {Pony} from "../../models/pony.model"; 
@Component({ 
    selector: 'el-ponies', 
    templateUrl: 'ponies.component.html', 
    providers: [PonyService] 
}) 
export class PoniesComponent { 
    ponies: Array<Pony>; 
    constructor(private ponyService: PonyService) { 
    this.ponies = this.ponyService.getPonies(2); 
    } 
    refreshPonies() { 
    this.ponies = this.ponyService.getPonies(3); 
    } 
} 

服务:

import {Injectable} from "@angular/core"; 
import {Http} from "@angular/http"; 
import {Pony} from "../../models/pony.model"; 
@Injectable() 
export class PonyService { 
    constructor(private http: Http) {} 
    getPonies(count: number): Array<Pony> { 
    let toReturn: Array<Pony> = []; 
    this.http.get('http://localhost:8080/js-backend/ponies') 
    .subscribe(response => { 
     response.json().forEach((tmp: Pony)=> { toReturn.push(tmp); }); 
     if (count && count % 2 === 0) { toReturn.splice(0, count); } 
     else { toReturn.splice(count); } 
    }); 
    return toReturn; 
    }} 

组件单元测试:

import {TestBed} from "@angular/core/testing"; 
import {PoniesComponent} from "./ponies.component"; 
import {PonyComponent} from "../pony/pony.component"; 
import {PonyService} from "../../services"; 
import {Pony} from "../../models/pony.model"; 
describe('Ponies component test',() => { 
    let poniesComponent: PoniesComponent; 
    beforeEach(() => { 
    TestBed.configureTestingModule({ 
     declarations: [PoniesComponent, PonyComponent], 
     providers: [{provide: PonyService, useClass: MockPonyService}] 
    }); 
    poniesComponent = TestBed.createComponent(PoniesComponent).componentInstance; 
    }); 
    it('should instantiate component',() => { 
    expect(poniesComponent instanceof PoniesComponent).toBe(true, 'should create PoniesComponent'); 
    }); 
}); 

class MockPonyService { 
    getPonies(count: number): Array<Pony> { 
    let toReturn: Array<Pony> = []; 
    if (count === 2) { 
     toReturn.push(new Pony('Rainbow Dash', 'green')); 
     toReturn.push(new Pony('Pinkie Pie', 'orange')); 
    } 
    if (count === 3) { 
     toReturn.push(new Pony('Fluttershy', 'blue')); 
     toReturn.push(new Pony('Rarity', 'purple')); 
     toReturn.push(new Pony('Applejack', 'yellow')); 
    } 
    return toReturn; 
    }; 
} 

的package.json的部分:

{ 
    ... 
    "dependencies": { 
    "@angular/core": "2.0.0", 
    "@angular/http": "2.0.0", 
    ... 
    }, 
    "devDependencies": { 
    "jasmine-core": "2.4.1", 
    "karma": "1.2.0", 
    "karma-jasmine": "1.0.2", 
    "karma-phantomjs-launcher": "1.0.2", 
    "phantomjs-prebuilt": "2.1.7", 
    ... 
    } 
} 

当我执行“因果报应的开始”我得到这个错误

Error: Error in ./PoniesComponent class PoniesComponent_Host - inline template:0:0 caused by: No provider for Http! in config/karma-test-shim.js

看起来人缘使用PonyService而不是嘲笑它作为MockPonyService,尽管在这方面的:providers: [{provide: PonyService, useClass: MockPonyService}]

问题:我该如何嘲笑服务?

回答

15

这是因为这个

@Component({ 
    providers: [PonyService] <====== 
}) 

这使得这样服务的作用范围是组件,这意味着角将创建它的每个组成部分,也意味着它会取代所有在配置的任何全球供应商模块级别。这包括您在测试平台中配置的模拟提供程序。

为了解决这个问题,Angular提供了TestBed.overrideComponent方法,它允许我们覆盖诸如@Component.providers@Component.template之类的东西。

TestBed.configureTestingModule({ 
    declarations: [PoniesComponent, PonyComponent] 
}) 
.overrideComponent(PoniesComponent, { 
    set: { 
    providers: [ 
     {provide: PonyService, useClass: MockPonyService} 
    ] 
    } 
}); 
+0

+1。但由于该服务是完全无状态的,它应该是一个单例,并且在模块提供者而不是组件提供者中声明。 –