angular - Angular2 / Jasmine: Testing Service with another Service as a dependency -


setup: app_initializer service configurationservice, loads config data, being used across app components , services. when unit testing components, reads config file , evaluates correctly. when unit testing services, use configuration, fails.

it set follows:

app.module.ts

export function configurationfactory( config: configurationservice ): {   // line triggers loading of config file     return () => config.load();  }  @ngmodule({   bootrstrap: {},   ...,   providers : [     configurationservice,     {       deps: [ configurationservice ],       multi: true,       provide: app_initializer,       usefactory: configurationfactory,        }   ] }) 

configurationservice.ts

@injectable() export class configurationservice {    // error holder   public error: boolean = false;   // data holder   public data: = {};   // config file url   private configurl: string = './assets/config/config.json';    constructor( private http: http ) {   }   /**    * reads config file    */   public load(): promise<any> {     return this.http.get( this.configurl )       .map( ( response: ) => response.json() )       .topromise()       .then( ( data: ) => this.data = data )       .catch( ( err: ) => promise.resolve() );   }  } 

here testableservice.service.ts uses config service, too

@injectable() export class testableservice extends someabstracthttpservice {   constructor( http: http,                private config: configurationservice ) {     super( http );   }    public setrequest( sessionid: string, isident: boolean ): void {     if ( isident ) {       this.resourceurl = `${ this.config.data.contextrootrest}/documents/ident/${sessionid}`;     } else {       this.resourceurl = `${ this.config.data.contextrootrest}/documents/noident/${sessionid}`;     }     this.headers = new headers();     this.headers.append( 'content-type', 'application/json' );     this.headers.append( 'accept', 'application/json, application/pdf' );     this.requestoptions = new requestoptions( {       headers: this.headers,       responsetype: responsecontenttype.blob     } );   } } 

now spec file, testableservice.service.spec.ts

export function configurationfactory( config: configurationservice ): {   return () => config.load(); }  describe( 'testableservice', () => {    // not ideal hardcode here, prefer using same config file, used across app!   let mockconfig: = {contextrootrest: 'rest/'};   let theservice: testableservice;     beforeeach( async(() => {     testbed.configuretestingmodule( {       imports: [         httpmodule,       ],       providers: [         testableservice,         mockdataservice,         { provide: xhrbackend, useclass: mockbackend },         configurationservice,         {           // provider app_initializer           deps: [ configurationservice ],           multi: true,           provide: app_initializer,           usefactory: configurationfactory,         },       ]     } );   } ) );    // suspect, using app_initializer @ stage goofy,    // not in fact instantiate app, service.    // correct way here?    beforeeach( inject( [ testableservice, xhrbackend ], ( service: testableservice, backend: mockbackend ) => {     theservice = service;     mockbackend = backend;   } ) );      it( 'should set request correctly', ( ) => {     theservice.setrequest( '1234567890', true );     expect( theservice.resourceurl )         .toequal( `${ mockconfig.contextrootrest }/documents/ident/1234567890` );   }); }); 

and fails expected 'undefined/documents/ident/1234567890' equal 'rest/documents/ident/1234567890' - means, config service has not been loaded @ testableservice @ all. ideas?

the code above bad. figured out way couple of hours later , here cleaner , better solution.

so, config file in our assets directory, can import directly spec file. have used mocked provider configurationservice , that's it. here spec.ts file

import { configurationservice } '../../common/config/configuration.service'; import * config '../../../assets/config/config.json';  const mockconfig: = config;  export class configurationfactory {   // no methods in original configurationservice, object var   public data: = mockconfig; }  describe( 'testableservice', () => {    let theservice: testableservice;    beforeeach( () => {     testbed.configuretestingmodule( {       providers: [         testableservice, ...         { provide: configurationservice, useclass: configurationfactory },       ]     } );   } );    beforeeach( inject( [ testableservice ],       ( service: testableservice ) => {         theservice = service;   } ) );    it( 'should set request correctly', ( ) => {     theservice.setrequest( '1234567890', true );     expect( theservice.resourceurl )         .toequal( `${ mockconfig.contextrootrest }/documents/ident/1234567890` );   }); } 

another example of things being solved in ways complicated simpler solution on surface... :/


Comments

Popular posts from this blog

angular - Ionic slides - dynamically add slides before and after -

minify - Minimizing css files -

Add a dynamic header in angular 2 http provider -