3

I'm pretty confused about how to test a data service, there's just way too many possibilities and it's overwhelming.

I have this simple service:

@Injectable()
export class DataService {

  constructor(private _http: HttpClient) { }

  getData<T>(path: string): Observable<T> {
    return this._http.get<T>(path);
  }

}

I want to test that calling getData<number> will, infact, return a data type of number.

The angular testing guide frustratingly shows several ways (use testbed, use beforeEach, use jasmine without testBed) and I've tried all of them but not with much success.

How do I do this please? I have so far failed to even get as far as calling the getData. I want to be able to mock the Http, emit mock return values (like in jasmine.spy.and.returnValue(mockData)) and verify that dataService is OK

I've got this in my data.service.spec.ts:

describe('DataService', () => {

  beforeEach(() => {

    TestBed.configureTestingModule({
      imports: [
        HttpClientModule
      ],
      providers: [
        DataService,
        HttpClient
      ]
    });

  });

  // This was auto generated, and works
  it('should be created', inject([DataService], (service: DataService) => {
    expect(service).toBeTruthy();
  }));

  // I added this, but doesn't work
  describe('When getData() is called', () => {

    it('should return an observable of type T', inject([DataService], (service: DataService) => {

      service.getData<number>('mock-url')
        .subscribe(data => {
          expect(typeof(data)).toBe('number');
        });

    }));

  });

});

When I say it doesn't work... the second test passes! but it shouldn't. I can see the real request go out on dev console to the (invalid) url, and that errors out as expected, but the test just passes...

So I guess, my question is simply, in Angular 5, how do I mock my backend service and unit test it please?

1 Answer 1

3

try to test it like this using flush method

 inject(
  [HttpTestingController, DataService],
  (httpMock: HttpTestingController, service: DataService) =>{
     const mockResponse = 5;
     const mock-url = '...';

     service.getData<number>('mock-url').subscribe(data => {
        expect(data).toEqual(mockResponse);
         expect(typeof(data)).toBe('number');
    });

    const mockRequest = httpMock.expectOne((req: HttpRequest<any>) => req.url === mock-url); //get your request here

    expect(mockRequest.request.method).toBe('GET');

    mockRequest.flush(mockResponse);
   })
Sign up to request clarification or add additional context in comments.

4 Comments

Hi - thanks for that. I get a httpMock.expectOne is not a function error. Do I need to initialise it before calling?
did you add HttpClientTestingModule in your TestBed.configureTestingModule ?
Yup! it's added into the providers array!
Hi, this started working after I removed HttpClient, HttpTestingController from providers. Found from here: stackoverflow.com/a/45482697/435867

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.