Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to mock HttpClient in a provided service in a component test in Angular?

Let's say I have a service that makes use of HttpClient,

@Injectable()
export class MyService {
  constructor(protected httpClient: HttpClient) { .. }
}

And then a component that makes use of this service.

@Component({
  selector: 'my-component'
})

export class SendSmsComponent {
  constructor(private MyService) { .. }
}

How to test this component while mocking the HttpClient and not the whole service?

TestBed.configureTestingModule({
  declarations: [MyComponent],
  providers: [
    { provide: MyService, useClass: MyService } // ?
  ]
}).compileComponents();

httpMock = TestBed.get(HttpTestingController); // ?
like image 403
Martin Avatar asked Oct 25 '17 10:10

Martin


People also ask

How can you mock the HTTP call in Angular?

You can put the response json in the asset folder and do the testing. You can also configure the url to be selected based on the environment variable so that in the prod build actual url will be taken and in dev the dummy one.

Can we mock HttpClient?

HttpClient's extensibility lies in the HttpMessageHandler passed to the constructor. Its intent is to allow platform specific implementations, but you can also mock it. There's no need to create a decorator wrapper for HttpClient.

Which method is used to mock the service method response in Angular?

Prefer spies as they are usually the best way to mock services. These standard testing techniques are great for unit testing services in isolation. However, you almost always inject services into application classes using Angular dependency injection and you should have tests that reflect that usage pattern.

What controller do you use in Angular to mock remote data for testing?

The HttpClientTestingModule allows you to easily mock HTTP requests by providing you with the HttpTestingController service.


2 Answers

To mock HttpClient you can use HttpClientTestingModule with HttpTestingController

Sample code to accomplish the same

import { TestBed, ComponentFixture } from '@angular/core/testing';
import { Type } from '@angular/core';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { SendSmsComponent } from './send-sms/send-sms.component';
import { ApiService } from '@services/api.service';

describe('SendSmsComponent ', () => {
  let fixture: ComponentFixture<SendSmsComponent>;
  let app: SendSmsComponent;
  let httpMock: HttpTestingController;

  describe('SendSmsComponent ', () => {
    beforeEach(async () => {
      TestBed.configureTestingModule({
        imports: [
          HttpClientTestingModule,
        ],
        declarations: [
          SendSmsComponent,
        ],
        providers: [
          ApiService,
        ],
      });

      await TestBed.compileComponents();

      fixture = TestBed.createComponent(SendSmsComponent);
      app = fixture.componentInstance;
      httpMock = fixture.debugElement.injector.get<HttpTestingController>(HttpTestingController as Type<HttpTestingController>);

      fixture.detectChanges();
    });

    afterEach(() => {
      httpMock.verify();
    });

    it('test your http call', () => {
      const dummyUsers = [
        { name: 'John' },
      ];

      app.getUsers();
      const req = httpMock.expectOne(`${url}/users`);
      req.flush(dummyUsers);

      expect(req.request.method).toBe('GET');
      expect(app.users).toEqual(dummyUsers);
    });
  });
});
like image 147
Siddhartha Gupta Avatar answered Oct 13 '22 08:10

Siddhartha Gupta


This is the approach I follow while testing HttpClient

  1. Create mock HttpClient object

    const httpClientSpy = jasmine.createSpyObj('HttpClient', ['post', 'get']);
    
  2. Injecting mock object in providers

    providers: [{ provide: HttpClient, useValue: httpClientSpy }]
    
  3. Return dummy valued within beforeEach() or it()

    httpClientSpy.post.and.returnValue(of({ status: 200, data: {} }));
    httpClientSpy.get.and.returnValue(of({ status: 200, data: {} }));
    
  4. Example test case

    it('should return data for abc endpoint', () => {
      service.methodWithHttpRequest().subscribe(data => expect(data.status).toBe(200));
    });
    
like image 35
Aakash Goplani Avatar answered Oct 13 '22 07:10

Aakash Goplani