We have a generic service to make and receive calls to backend controllers. In Angular 4 all the tests were working, but due to new libraries and changes they no longer work. I am now trying to re-write these using HttpClientTestingModule
and HttpTestingController
.
So our concrete class has a number of functions and for the moment I'm concentrating on our getRequest
method:
constructor(
private configService: ConfigService,
private userService: UserService,
private httpClient: HttpClient,
private errorMapperService: ErrorMapperService) {
}
public getRequest(uri: string): Observable<any> {
const fullUri = this.buildServiceUri(uri);
const requestHeaders = this.getDefaultRequestHeadersObservable();
return forkJoin(fullUri, requestHeaders)
.pipe(flatMap((results: [string, HttpHeaders]) => this.httpClient.get(results[0], { withCredentials: true, headers: results[1] })),
catchError(this.errorMapperService.handleError));
}
At the moment in my spec file I have:
fdescribe('Api Service', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
HttpClientModule,
HttpClientTestingModule
],
providers: [
{ provide: ApiService },
{ provide: ConfigService },
{ provide: ErrorMapperService },
{ provide: UserService }
]
});
});
describe('getRequest', () => {
const uiServiceUri: string = 'uiServiceUri';
const expectedResponse: any = { data: '1234', myDate: new Date(2017, 0, 1, 0, 0, 0) };
const user = new User();
user.userSession = '<SESSIONTOKEN>';
let configService: ConfigService;
let userService: UserService;
let apiService: ApiService;
let errorMapperService: ErrorMapperService;
let httpTestingController: HttpTestingController;
beforeEach(() => {
configService = TestBed.get(ConfigService);
userService = TestBed.get(UserService);
apiService = TestBed.get(ApiService);
errorMapperService = TestBed.get(ErrorMapperService);
httpTestingController = TestBed.get(HttpTestingController);
});
describe('with response object',
() => {
it('Gets expected response and converts dates to date objects', async(() => {
apiService.getRequest('test')
.subscribe((responseObject) => {
expect(responseObject).toEqual(expectedResponse);
});
httpTestingController.expectOne('test').flush(expectedResponse);
httpTestingController.verify();
}));
});
});
The issue is that if I initially leave out the last 2 lines of code against the httpTestingController, then my expect never gets reached and the test harness says 'no expectation found'. If I introduce those 2 lines back in, then I receive a fail that states:
Failed: Expected one matching request for criteria "Match URL: test", found none. Requests received are: GET http://localhost:9876/api/User/, GET http://localhost:9876/api/Config/UiServiceUri, GET http://localhost:9876/api/User/.
So then I change the URL to the main one such that the test controller line becomes:
httpTestingController.expectOne('http://localhost:9876/api/User/');
then I receive a similar error stating that only one was expected, but found 2. I'm guessing this is because of my constructor of the concrete class. How should I be writing this test?