2016-10-29 181 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。但由於該服務是完全無狀態的,它應該是一個單例,並且在模塊提供者而不是組件提供者中聲明。 –