Search code examples
angulartypescriptkarma-jasmineangular-unit-test

Writing test cases for Http service in angular


Hi I have been trying to write test cases for my registration service. It has a url which it sends 4 values. the service is as follows:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http'



interface registerResponse {
  success: boolean,
  message: string
}

@Injectable()
export class AuthService {

private _regurl ="http://localhost:3000/api/register"
  constructor(private http: HttpClient) { }



  registerUser(username,email,date,  password) {
   
    return this.http.post<registerResponse>(this._regurl, {
      username,
      email,
      date,
      password
      
     
    })
  }

}

I am still learning how to write test cases, i m trying to get the registerResponse to work.

here is what i have written till now

import { TestBed, async, inject } from '@angular/core/testing';
import {
  HttpModule,
  Http,
  Response,
  ResponseOptions,
  XHRBackend
} from '@angular/http';
import { MockBackend } from '@angular/http/testing';
import { AuthService } from './auth.service';
import { HttpClient } from '@angular/common/http'


describe('RegisterService', () => {

  beforeEach(() => {

    TestBed.configureTestingModule({
      imports: [HttpModule],
      providers: [
        { provide: HttpClient, useValue: 'http://localhost:3000/api/register' },
        AuthService,
        { provide: XHRBackend, useClass: MockBackend },
      ]
    });
  });

I know its not much I hv only defined mockbackend but any help would be appriciated

Thank You


Solution

  • To begin testing calls to HttpClient, import the HttpClientTestingModule and the mocking controller,HttpTestingController, along with the other symbols your tests require.

    import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
    

    Then add the HttpClientTestingModule to the TestBed and continue with the setup of the service-under-test.

    import { TestBed } from '@angular/core/testing';
    import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
    
    describe('RegisterService', () => {
    
      let service: AuthService;
      let httpMock: HttpTestingController;
    
      beforeEach(() => {
    
        TestBed.configureTestingModule({
          imports: [HttpClientTestingModule],
          providers: [AuthService]
        });
    
        service = TestBed.get(AuthService);
        httpMock = TestBed.get(HttpTestingController);
      });
    
      afterEach(() => {
        httpMock.verify();
      });
    
      describe('#registerUser tests', () => {
        it('Should return registerResponse by making a POST request to the given url', () => {
    
          const username = 'username';
          const email = 'email';
          const date = 'date';
          const password = 'password';
    
          const mockResponse: RegisterResponse = {
            success: true,
            message: 'Successfull'
          };
          service.registerUser(username, email, date, password).subscribe((res) => {
            expect(res).toBe(mockResponse);
          });
    
          const req = httpMock.expectOne('http://localhost:3000/api/register');
          expect(req.request.method).toBe('POST');
          req.flush(mockResponse);
        });
      });
    });
    

    Now requests made in your tests will hit the testing backend instead of the normal backend.

    This setup also calls TestBed.get() to inject the mocking controller so it can be referenced during the tests.

    The following expectOne() will match the request's URL.If no requests or multiple requests matched that URL expectOne() would throw.

    const req = httpMock.expectOne('http://localhost:3000/api/register');
    

    Read more about testing angular services that uses HttpClient and testing Http requests in official angular documentation.

    In your service. Export the innterface.

    export interface RegisterResponse {
      success: boolean,
      message: string
    }
    

    But I recommend you to move data models to a different directory or a file.

    Then import the interface to the tes file like this.

    import { RegisterResponse } from 'path-to-interface';