I am new in angular unit testing; I want to write a unit test for the service that is injected in constructor and is called http in it . but I don't know why globalConfig property is undefined:
@Injectable({
providedIn: "root",
})
export class GlobalConfigService {
globalConfig: GlobalConfig= new GlobalConfig();
constructor(private http: HttpClient, private configService: ConfigService) {
if (configService.getData() == undefined){
let data:any;
http.get('./assets/config/config.json').subscribe(
ok => {
data = ok;
http.get<any>(data.baseUrl + 'config/app').subscribe(
response => {
response.baseUrl = data.baseUrl;
configService.setData(response);
this.globalConfig = <GlobalConfig>{
baseUrl: configService.getData()["baseUrl"],
language: configService.getData()["language"],
};
},
error => {
console.log(error);
}
)
},
error => {
console.log(error);
}
)
}
else{
this.globalConfig = <GlobalConfig>{
baseUrl: configService.getData()["baseUrl"],
language: configService.getData()["language"],
};
}
}
get Config(): Promise<GlobalConfig> {
return new Promise((resolve, reject) => {
resolve(this.globalConfig);
});
}
get appConfig(): GlobalConfig {
return this.globalConfig;
}
}
The unit test I've written is:
describe('GlobalConfigService', () => {
let httpTestingController: HttpTestingController;
let ConfigServiceSpy: ConfigService;
let mockGlobalConfig: GlobalConfigService;
beforeEach(() => {
ConfigServiceSpy = jasmine.createSpyObj('ConfigService', ['getData','setData']);
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [GlobalConfigService, {provider: ConfigService, useValue: ConfigServiceSpy}]
});
httpClient = TestBed.inject(HttpClient);
httpTestingController = TestBed.inject(HttpTestingController);
mockGlobalConfig = TestBed.inject(GlobalConfigService);
ConfigServiceSpy = TestBed.inject(ConfigService);
});
it('should return config ', () => {
let response = {
baseUrl: "http://localhost:8080/",
language: "fa",
};
const req = httpTestingController.expectOne(
"./assets/config/config.json"
);
expect(req.request.method).toEqual("GET");
req.flush(response);
expect(mockGlobalConfig.appConfig.baseUrl).toBe(response.baseUrl);
});
but this error occurs : Expected undefined to be 'http://localhost:8080/ what should I do ?
Your logic is called in the constructor, my guess is that it's too late when you flush. You should try to spy/mock your service dependencies, not use testBed nor HttpClientTestingModule and create a new instance of your service with your mocks as parameters.Then you should be able to assert as your value mocks would be there during subscription in the constructor.
https://angular.io/guide/testing-services#testing-http-services
Also you should clean your code in your constructor: encapsulate parts of logic in methods to be more readable, and try not to nest subscribes but use rxjs operators https://rxjs.dev/guide/overview