How to mock HTTP Request in Angular?
Asked Answered
S

6

14

I have checked a lot of articles and answers but I don't seem to find the right way to mock HTTP Requests for my methods. I want to test my frontend application independently from the backend. Here is the type of methods I have:

 private getProfile() {
    this.http
      .get('go/profile/get', {withCredentials: true})
      .subscribe((profile: Profile) => {
        this.user.profile = profile;
        this.updateLineMsgs();
      });
  }

Any suggestions ?

Scimitar answered 20/11, 2019 at 9:24 Comment(0)
G
9

Usually i mock my Http requests with HttpClientTestingModule :

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

export class TestService {
    constructor(private http: HttpClient) {}
}

describe('AppInterceptor', () => {
    let service: TestService;
    let httpMock: HttpTestingController;

    beforeEach(() => {
        TestBed.configureTestingModule({
            imports: [HttpClientTestingModule],
            providers: [
                TestService
            ]
        });
        service = TestBed.inject(TestService);
        httpMock = TestBed.inject(HttpTestingController);
    });

//...
const httpRequest = httpMock.expectOne('any-url');
Gigantes answered 20/11, 2019 at 9:33 Comment(1)
A mock is supposed to give an answer to a request.Syverson
V
9

You can always create a mock method by your own and mock the response that you expect from the backend. In your example it could be

 public static mockGetProfile(){
    const response = JSON.parse(`
     "name": "abc",
     "active": true,
     ...all other json fields that you want
     `);

    let obs = new Observable((subscriber) => {
        setTimeout(()=>{
            subscriber.next(response);
            subscriber.complete();
        }, 3000);
    });
    return obs;
}

The above observable will complete after 3 seconds or what ever period you define, simulating in a way the response from a backend server which will need some time to be available.

Vanscoy answered 7/12, 2020 at 15:46 Comment(0)
C
3

If I understand your question correctly, you want to create your frontend services before your backend, but you still want to use promises / observables. You can use of for that:

import { of } from 'rxjs';
//emits any number of provided values in sequence
const source = of(1, 2, 3, 4, 5);
//output: 1,2,3,4,5
const subscribe = source.subscribe(val => console.log(val));

from https://www.learnrxjs.io/operators/creation/of.html

Comyns answered 20/11, 2019 at 9:29 Comment(0)
W
3

in order to fake the backend server response, you need to create a service that implements the HttpInterceptor interface

https://medium.com/@lanoTechno/intro-to-angular-http-interceptors-and-how-to-create-backendless-app-with-them-3593f6552b3a

Weighty answered 20/11, 2019 at 9:31 Comment(0)
S
0

Option 1:

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

describe('ContinentService', () => {
let service: ContinentService;

beforeEach(() => {
    TestBed.configureTestingModule({ imports: 
    [HttpClientTestingModule] });
    service = TestBed.inject(ContinentService);
});

it('should be created', async () => {
expect(service).toBeTruthy();
const httpMock = TestBed.inject(HttpTestingController);

const response = 
  {
    id: 'some-id',
    data: 'fancy profile data'
  };

  // unfortunately, you can't use async/await!
  // const result = await service.countries$.toPromise();
  service. getProfile().subscribe((result) => {
    expect(result[0].name).toBe('España');
  });

   const mockRequest = httpMock.expectOne('go/profile/get');
   mockRequest.flush(countries);
 });
});

More information:

https://www.beyondjava.net/jest-mocking-an-angular-service

Smallscale answered 14/1, 2023 at 23:18 Comment(0)
T
-3

You can put the response json in the asset folder and do the testing.

For example create a test.json file under assets/json and change your url accordingly

private getProfile() {
    this.http
      .get('assets/json/test.json', {withCredentials: true})
      .subscribe((profile: Profile) => {
        this.user.profile = profile;
        this.updateLineMsgs();
      });
  }

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.

Titan answered 20/11, 2019 at 9:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.