0

I am attempting to write a helper function in an Angular test leveraging HttpTestingController. The reason being is because I will eventually have a series of endpoints within my Angular service, RequestService, that I want to test within this testing file. I do not want to repeatedly inject my RequestService and HttpTestingController instances into each test function that tests the service. That is redundant. Rather, I would prefer to have a single test function that takes the injected RequestService and HttpTestingController instances and repeatedly passes them into the helper function I have created, requestHelper. This way when I want to test additional endpoints, all I need to do is make a call to the helper function and provide the parameters that are needed.

The problem I am bumping into is that when the helper function runs, the service's instance for some reason does not appear to exist, Even though the test is able to access the service's functions. When it reaches my service method's call to the http.get within the callEndpoint function, it gives me the below error:

Failed: Cannot read property 'http' of undefined

This does not make sense to me because the this keyword is referring to the instance of the Angular service, and the test case is able to reach the service's function, so how could this possibly be undefined?

Here is my test spec:

import { TestBed, async, inject } from '@angular/core/testing';
import { HttpClientModule, HttpRequest, HttpParams } from '@angular/common/http';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import {  RequestService } from './request.service';

describe(`RequestService`, () => {

      beforeEach(async(() => {
        TestBed.configureTestingModule({
          imports: [
            HttpClientModule,
            HttpClientTestingModule
          ],
          providers: [
            RequestService
          ]
        });
      }));

      afterEach(async(inject([HttpTestingController], (backend: HttpTestingController) => {
        backend.verify();
      })));

      it(`TESTING INJECTION`, async(inject([RequestService, HttpTestingController],
        (service: RequestService, backend: HttpTestingController) => {

         requestHelper(service.callEndpoint,'https://endpointurl.com',backend);
      })));

      function requestHelper(serviceCall: Function, url: string,  backendInstance: any) {
        serviceCall(...serviceParams).subscribe();
        backendInstance.expectOne((req: HttpRequest<any>) => {
          return req.url === url
              && req.method === 'GET';
        }, 'GET');
      }
});

And the respective service that the spec is testing

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { RequestOptions } from '@angular/http';
import { Observable } from 'rxjs/Observable';

    @Injectable()
    export class RequestService {

      private requestOptions = {
        headers: new HttpHeaders({'Locale': 'en_US'})
      };

      constructor(private http: HttpClient) { }

      callEndpoint(state: string, countryCode: string): Observable<Object> {
        return this.http.get(`https://endpointurl.com`,this.requestOptions);
      }
}

Thank you for your help!

7
  • Looks like this is undefined. Commented Mar 1, 2018 at 21:39
  • 1
    have you tried passing requestHelper(service.callEndpoint.bind(service)... ? Commented Mar 1, 2018 at 22:08
  • 1
    Adding .bind(service) to service.callEndpoint when passing it as a param to requestHelper should solve the issue Commented Mar 2, 2018 at 5:09
  • 1
    @BorisLobanov This did in fact solve the issue. Thank you! Would one of you like to post it as an answer? I will accept it. :) Commented Mar 2, 2018 at 14:49
  • 1
    I just did, thanks! Commented Mar 2, 2018 at 14:58

1 Answer 1

1

You can bind the context in the it block:

it(`TESTING INJECTION`, async(inject([RequestService, HttpTestingController],
    (service: RequestService, backend: HttpTestingController) => {

    requestHelper(service.callEndpoint.bind(service),'https://endpointurl.com',backend);
})));
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.