I’m adding unit tests to my API and had a bit of bother mocking the API response. However after a lot of console.log and much head scratching I found some voodoo that works.
TWO KEY TAKEAWAYS
1 . Josh Morony’s blog post said the call is
connection.mockRespond ( new Response ( newResponseOptions(...
That didn’t work for me, I had to use
connection.mockRespond ( newResponseOptions ( body: myObjects
2. But that’s not all, my live response (from a MS WebApi) has a ._body property, my mocked response has a .body. So I had to do something like this
if(res['body']){ //works with mocks
//...
}else if(res['_body']){//works in live system
//...
}
I started with this complete example:
git clone https://github.com/ionic-team/ionic-unit-testing-example.git
(The version numbers of the npm packages have to be compatible)
And worked through this blog post (and others!):
Test Driven Development in Ionic 2: Http and Mocks
This would have been a lot easier if I could figure out how to attach a debugger to Karma, no luck with that so far. Anyhow my complete dummy-service.spec.ts (including code for the service) is…
(just as soon as i figure out how to paste code into wordpress…)
import {Injectable} from '@angular/core';
import { Http, HttpModule, XHRBackend, ResponseOptions, Response } from '@angular/http';
import { TestBed, inject } from '@angular/core/testing';
import { MockBackend } from '@angular/http/testing';
@Injectable()
export class DummyService {
access_token:string;
constructor(public http:Http){}
get(){
console.log('DummyService Test1 F');
this.http.get('http://localhost').subscribe((res:Response)=>{
console.log('DummyService Test1 G got ' + JSON.stringify(res));
if(res['body'] && res['body']['access_token']){
this.access_token = res['body']['access_token']; //works with mocks
console.log('loginUser got token from body (we are using a mock)');
}else if(res['_body'] && JSON.parse(res['_body'])
&& JSON.parse(res['_body']).access_token){
this.access_token = JSON.parse(res['_body']).access_token; //works with live system
console.log('loginUser got token from _body (we are live)');
}
console.log('access_token is ' + this.access_token);
});
}
}
describe ('DummyService http method',()=>{
beforeEach(()=>{
TestBed.configureTestingModule(
{
imports:[HttpModule],
providers:[
{provide: XHRBackend, useClass:MockBackend},
DummyService
]
}
);
}
);
it('should call get and get response',inject([DummyService, XHRBackend],(dummyService, mockBackend)=>{
console.log('DummyService Test1 A');
let r1 = "hello"; //works
let r2 = "{access_token:'SOMETOKEN'}"; //works
let r3 = //doesn't work, service gets empty object {}
new Response(
new ResponseOptions(
{
url:'url',
status:200,
body: "here is the info"
}
)
);
let r4 = JSON.stringify(r3);//doesn't work, service gets empty object {}
let r5 = new ResponseOptions( //aha THIS is the bunny...
{
body: {access_token:'SOMETOKEN'}
}
);
mockBackend.connections.subscribe(
connection=>{
console.log('DummyService Test1 D v4 r5');
connection.mockRespond(r5);
}
);
console.log('DummyService Test1 B');
dummyService.get();
console.log('DummyService Test1 C');
expect(dummyService.access_token).toEqual('SOMETOKEN');
}));
});