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
Post a Comment