【发布时间】:2017-09-12 10:18:11
【问题描述】:
设置:加载配置数据的 APP_INITIALIZER 服务ConfigurationService 正在跨应用组件和服务使用。在对组件进行单元测试时,它会读取配置文件并正确评估。对使用配置的服务进行单元测试时,它会失败。
设置如下:
app.module.ts
export function ConfigurationFactory( config: ConfigurationService ): any {
// this line actually triggers the loading of the 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: any = {};
// 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: any ) => response.json() )
.toPromise()
.then( ( data: any ) => this.data = data )
.catch( ( err: any ) => Promise.resolve() );
}
}
这里也是使用配置服务的TestableService.service.ts
@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
} );
}
}
现在是规范文件,TestableService.service.spec.ts
export function ConfigurationFactory( config: ConfigurationService ): any {
return () => config.load();
}
describe( 'TestableService', () => {
// not ideal to hardcode it here, I would prefer using the same config file, which is used across the app!
let mockConfig: any = {contextRootRest: 'rest/'};
let theService: TestableService;
beforeEach( async(() => {
TestBed.configureTestingModule( {
imports: [
HttpModule,
],
providers: [
TestableService,
MockDataService,
{ provide: XHRBackend, useClass: MockBackend },
ConfigurationService,
{
// Provider for APP_INITIALIZER
deps: [ ConfigurationService ],
multi: true,
provide: APP_INITIALIZER,
useFactory: ConfigurationFactory,
},
]
} );
} ) );
// I suspect, that using APP_INITIALIZER at this stage is goofy,
// as I do not in fact instantiate the app, only the service.
// What would be the correct way to do it 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` );
});
});
它以Expected 'undefined/documents/ident/1234567890' to equal 'rest/documents/ident/1234567890' 失败 - 这意味着配置服务根本没有在 TestableService 中加载。有什么想法吗?
【问题讨论】:
标签: angular unit-testing dependency-injection jasmine