![](/img/trans.png)
[英]Angular2 unit test Http MockBackend issue - Cannot read property merge of undefined at mergeOptions
[英]How to do a unit test for Http get MockBackend in Angular2?
如何在Angular2中為Http獲取MockBackend進行單元測試?
我在測試我的http單元測試時遇到了麻煩。 每次我看MockBackend
看起來都很混亂,很多代碼和一些導入都無法正常工作。
我只想要一個非常基本的http get單元測試
我正在使用:typescript,angular2,jasmine和karma runner。
我的實際代碼運行正常。
這是我正在測試的代碼:
import {Injectable} from 'angular2/angular2';
import {HTTP_PROVIDERS, Http, Headers} from 'angular2/http';
@Injectable()
export class FirebaseService{
headers: Headers;
//Test issue seems to be here when I inject Http instance.
constructor(public http?: Http) {
this.headers = new Headers();
this.headers.append('Content-Type', 'application/json');
}
//This is the method I'm testing.
public getSpotifyTracks = ():Promise<Object> =>{
return this.http
.get('https://api.spotify.com/v1/tracks/0eGsygTp906u18L0Oimnem', {headers:this.headers})
.map((response) => {
return response.json()
}).toPromise();
}
}
這是我對該代碼的單元測試:
import {it, iit, describe, expect, inject, injectAsync, beforeEachProviders, fakeAsync, tick} from 'angular2/testing';
import {HTTP_PROVIDERS, Http, Headers} from 'angular2/http';
import {FirebaseService} from '../app/firebase-service';
describe('Firebase Service Calls', () => {
beforeEachProviders(()=> [Http, FirebaseService]);
//Issue seems to be here????
it('get all tracks from spotify', injectAsync([FirebaseService],(service) => {
return service.getSpotifyTracks().then((response) => {
expect(response.length).not.toBe(null);
});
}), 3000);
});
首先導入所有模塊:
import {it,describe,expect,inject,injectAsync,beforeEachProviders} from 'angular2/testing';
import {provide, Injector} from 'angular2/core';
import {MockBackend} from 'angular2/http/testing';
import {YourServiceToBeTested} from 'path/to/YourServiceToBeTested';
接下來,您需要聲明Mocked HttpBackend:
describe('Service with Http injected', () => {
beforeEachProviders(() => {
[
MockBackend,
BaseRequestOptions,
provide(
Http,
{
useFactory: (backend, defaultOptions) => {
return new Http(backend, defaultOptions);
},
deps: [MockBackend, BaseRequestOptions]
}),
YourServiceToBeTested
]
});
最后在每個測試中,您需要注入模擬並設置模擬值(即您的服務為此特定測試返回的假數據)
it('should respect your expectation',
inject(
[YourServiceToBeTested, MockBackend],
(yourServiceToBeTested, mockBackend) => {
let response = 'Expected Response from HTTP service usually JSON format';
let responseOptions = new ResponseOptions({body: response});
mock.connections.subscribe(
c => c.mockRespond(new Response(responseOptions)));
var res = yourServiceToBeTested.ServiceMethodToBeTest(serviceParams);
expect(res).toEqual('your own expectation');
}));
雖然@ f-del的答案得到了相同的結果,但這更容易並且更好地使用Angulars DI。
describe('Firebase Service Calls', () => {
beforeEachProviders(()=> [
HTTP_PROVIDERS,
MockBackend,
provide(XHRBackend, {useExisting: MockBackend})]);
這樣,當請求Http
時,提供了使用MockBackend
實例。
在Angular 2.2.1中提供的核心不再存在,所以我們應該這樣做:
{
provide : Http,
deps : [ MockBackend, BaseRequestOptions ],
useFactory : ( backend : MockBackend, defaultOptions : BaseRequestOptions ) => {
return new Http( backend, defaultOptions );
}
}
為了捎帶@Milad的回復,我發現了一個關於模擬http調用 Angular 2/4單元測試的精彩教程 。
searchService.service.ts
import {Injectable} from '@angular/core';
import {Jsonp} from '@angular/http';
import 'rxjs/add/operator/toPromise';
class SearchItem {
constructor(public name: string,
public artist: string,
public thumbnail: string,
public artistId: string) {
}
}
@Injectable()
export class SearchService {
apiRoot: string = 'https://itunes.apple.com/search';
results: SearchItem[];
constructor(private jsonp: Jsonp) {
this.results = [];
}
search(term: string) {
return new Promise((resolve, reject) => {
this.results = [];
let apiURL = `${this.apiRoot}?term=${term}&media=music&limit=20&callback=JSONP_CALLBACK`;
this.jsonp.request(apiURL)
.toPromise()
.then(
res => { // Success
this.results = res.json().results.map(item => {
console.log(item);
return new SearchItem(
item.trackName,
item.artistName,
item.artworkUrl60,
item.artistId
);
});
resolve(this.results);
},
msg => { // Error
reject(msg);
}
);
});
}
}
searchService.service.spec.ts
describe('Service: Search', () => {
let service: SearchService;
let backend: MockBackend;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [JsonpModule],
providers: [
SearchService,
MockBackend,
BaseRequestOptions,
{
provide: Jsonp,
useFactory: (backend, options) => new Jsonp(backend, options),
deps: [MockBackend, BaseRequestOptions]
}
]
});
backend = TestBed.get(MockBackend);
service = TestBed.get(SearchService);
});
});
it('search should return SearchItems', fakeAsync(() => {
let response = {
"resultCount": 1,
"results": [
{
"artistId": 78500,
"artistName": "U2",
"trackName": "Beautiful Day",
"artworkUrl60": "image.jpg",
}]
};
// When the request subscribes for results on a connection, return a fake response
backend.connections.subscribe(connection => {
connection.mockRespond(new Response(<ResponseOptions>{
body: JSON.stringify(response)
}));
});
// Perform a request and make sure we get the response we expect
service.search("U2");
tick();
expect(service.results.length).toBe(1);
expect(service.results[0].artist).toBe("U2");
expect(service.results[0].name).toBe("Beautiful Day");
expect(service.results[0].thumbnail).toBe("image.jpg");
expect(service.results[0].artistId).toBe(78500);
}));
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.