angular - Hur gör man ett enhetstest för Http post, put, delete med MockBackend i Angular2?
Så jag testar mina Angular2-komponenter och tjänster.
Hittills har jag använt mockBackend för att mocka get-förfrågningar i tjänsten enligt nedan:
/* tslint:disable:no-unused-variable */
import { MockBackend } from '@angular/http/testing';
import { Http, ConnectionBackend, BaseRequestOptions, Response, ResponseOptions } from '@angular/http';
import { PagesService } from './pages.service';
import { tick, fakeAsync } from '@angular/core/testing/fake_async';
import { inject, TestBed } from '@angular/core/testing/test_bed';
import {GlobalService} from './../../shared/global.service';
describe('PagesService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
{
provide: Http, useFactory: (backend: ConnectionBackend, defaultOptions: BaseRequestOptions) => {
return new Http(backend, defaultOptions);
}, deps: [MockBackend, BaseRequestOptions]
},
{ provide: PagesService, useClass: PagesService },
{ provide: GlobalService, useClass: GlobalService },
{ provide: MockBackend, useClass: MockBackend },
{ provide: BaseRequestOptions, useClass: BaseRequestOptions }
]
});
});
//should retrive all search results
it('should retrieve all search results',
inject([PagesService, MockBackend], fakeAsync((pagesService: PagesService, mockBackend: MockBackend) => {
let res: Response;
mockBackend.connections.subscribe(c => {
expect(c.request.url).toBe('http://localhost:3200/pm/pages/');
let response = new ResponseOptions({
body: '[{"name": "Rapid"}, {"name": "NGBC"}]'});
c.mockRespond(new Response(response));
});
pagesService.getAllpages().subscribe((response) => {
res = response;
});
tick();
expect(res[0].name).toBe('Rapid');
}))
);
it('should fetch by Page id',
inject([PagesService, MockBackend], fakeAsync((pagesService: PagesService, mockBackend: MockBackend) => {
let res;
mockBackend.connections.subscribe(c => {
let page_id:string='2';
expect(c.request.url).toBe('http://localhost:3200/pm/pages/'+page_id);
let response = new ResponseOptions({body: '[{"id": 1, "name": "Rapid"}, {"id": 2, "name": "NGBC"}]'});
c.mockRespond(new Response(response));
});
pagesService.getPageById('2').subscribe((response) => {
res = response;
});
tick();
expect(res[1].name).toBe('NGBC');
}))
);
});
Om du vill se min service.ts är den som följer:
export class PagesService {
private headers = new Headers();
public baseUrl:string;
constructor(private http: Http,private _globalService:GlobalService) {
this.baseUrl=this._globalService.baseUrl;
}
getAllpages() {
return this.http.get(this.baseUrl + '/pm/pages/')
.map((res: Response) => res.json()).catch(this.handleError);
}
getPageById(page_id: string) {
return this.http.get(this.baseUrl + '/pm/pages/' + page_id)
.map((res: Response) => res.json()).catch(this.handleError);
}
savePage(page: Object) {
this.headers=new Headers();
this.headers.append('Content-Type', 'application/json');
let url = this.baseUrl+'/pm/pages/';
let data={};
data["data"]=page;
return this.http.post(url, JSON.stringify(data),{headers: this.headers})
.map((res: Response) => res.json()).catch(this.handleError);
}
updatePage(page: any) {
this.headers=new Headers();
this.headers.append('Content-Type', 'application/json');
let url = this.baseUrl+'/pm/pages/'+page._id;
let data={};
data["data"]=page;
return this.http.put(url, JSON.stringify(data),{headers: this.headers})
.map((res: Response) => res).catch(this.handleError);
}
deletePage(page_id: string) {
this.headers=new Headers();
this.headers.append('Content-Type', 'application/json');
let url = this.baseUrl+'/pm/pages/';
return this.http.delete(url + page_id,{headers: this.headers,body: ''})
.map((res: Response) => res).catch(this.handleError);
}
mergePage(page: Object) {
return this.http.post(this.baseUrl + '/pm/pages/',JSON.stringify(page))
.map((res: Response) => res.json()).catch(this.handleError);
}
handleError(error: any) {
console.error(error);
return Observable.throw(error.json().error || 'Server error');
}
}
Från ovanstående tjänst har jag implementerat metoderna getAllPages() och getPageById() i min service.spec.ts-fil korrekt eftersom de fungerar bra.
Jag vill veta hur man implementerar testfall för savePage() , updatePage() , deletePage()-metoderna.
Några synpunkter?
Tack i förväg.
Svar #1
Du behöver undersöka metodernas interna delar och se vad de gör. Detta är hur du testar dess förväntade beteende.
Du sätter Content-Type-headern. Så detta är ett krav, och du bör testa detta beteende. Du kan få headers från
MockConnection#requestbackend.connections.subscribe((conn: MockConnection) => { let contentType = conn.request.headers.get('Content-Type'); expect(contentType).not.toBeNull(); expect(contentType).toEqual('application/json'); });Du sätter URL:en, så detta är ett krav. Detta bör testas. Du redan
expect(conn.request.url).toBe('...');Du skickar data. Så detta är ett krav. Du bör testa för att säkerställa att datan är i det kravställda formatet/strukturen
let body = conn.request.json(); expect(body.data).toEqual('page');
Det är för förfrågningsdelen.
För svarsdelen bör du testa vad din tjänst gör med det svaret.
Om du tar emot en kropp bör du testa den som du gjorde med GET-förfrågan.
Du hanterar också felet med en felåteruppringning. Du behöver inte testa vad återuppringningen gör här. Det borde vara ett eget test. Allt vi vill testa är att felhanteraren kallas från metoden som testas. För det bör vi använda en spion. Vi kan spionera på
handleError-funktionen och sedan kontrollera att den har kallats.spyOn(service, 'handleError').and.callFake(() => {}); // make call tick(); expect(service.handleError).toHaveBeenCalled();Jag kunde inte hitta ett fall (med MockConnection) där
catch-metoden anropas på din Http-förfrågan, därför lade jag inte upp ett exempel. Jag försökteconn.mockError(new Error()), det fungerade inte. Jag försökte kasta ett fel inuti anslutningen, det fungerade inte. Kanske kan du lista ut det.
