dafyddPrys dafyddPrys - 2 months ago 17
TypeScript Question

using MockBackend to test function that then calls .map

I am trying to write unit tests for my service which makes Http requests.

I have a service that returns a

Http.get()
request followed by a
.map()
. I am having trouble getting my mocked backend to return something that doesn't error on the
.map()
. The error I'm getting is:

this._http.get(...).map is not a function


I have been using this article as my main guide throughout.

If I remove the
.map()
from my service function, I don't get any errors. How can I get my mocked response to have a
.map()
function that I can call?

Note: I am currently using RC.4

Here is my service:

import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http';
import { Observable } from 'rxjs/Observable';

import { AppSettings } from '../../../settings';
import { Brand } from '../../models/index';

@Injectable()
export class BrandDataService {

allBrands : Brand[];
groups : any;
groupNames : string[];

constructor (
private _http : Http
) {}

/**
* Get all brands
*/
public getAllBrands () :Observable<any> {

let url = AppSettings.BRAND_API_URL + 'brands';
return this._http.get( url )
.map( this.createAndCacheBrands )
.catch( (error) => {
return Observable.throw( error );
});
}

private createAndCacheBrands (res:Response) {
...
}

}


And here is my spec file, which is using
MockBackend
and other associated libraries to mock the backend for these tests:

// vendor dependencies
import { Http, BaseRequestOptions, Response, ResponseOptions, RequestMethod } from '@angular/http';
import { addProviders, inject } from '@angular/core/testing';
import { MockBackend, MockConnection } from '@angular/http/testing';

// Service to test
import { BrandDataService } from './brandData.service';


describe( 'Brand data service', () => {

let service : BrandDataService = null;
let backend : MockBackend = null;

// Provide a mock backend implementation
beforeEach(() => {
addProviders([
MockBackend,
BaseRequestOptions,
{
provide : Http,
useFactory : (backendInstance : MockBackend, defaultOptions : BaseRequestOptions) => {
return new Http(backendInstance, defaultOptions);
},
deps : [MockBackend, BaseRequestOptions]
},
BrandDataService
])
})

beforeEach (inject([BrandDataService, MockBackend], (_service : BrandDataService, mockBackend : MockBackend) => {
service = _service;
backend = mockBackend;
}));

it ('should return all brands as an Observable<Response> when asked', (done) => {
// Set the mock backend to respond with the following options:
backend.connections.subscribe((connection : MockConnection) => {
// Make some expectations on the request
expect(connection.request.method).toEqual(RequestMethod.Get);
// Decide what to return
let options = new ResponseOptions({
body : JSON.stringify({
success : true
})
});
connection.mockRespond(new Response(options));
});

// Run the test.
service
.getAllBrands()
.subscribe(
(data) => {
expect(data).toBeDefined();
done();
}
)
});
});

Answer

You need to import rxjs so you can use map:

import 'rxjs/Rx';

Or, you can import only map operator so your app doesn't load files you won't use:

import 'rxjs/add/operator/map';