12

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 ?

Basilius Mourk
  • 131
  • 1
  • 1
  • 5

6 Answers6

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.

Mario Petrovic
  • 7,500
  • 14
  • 42
  • 62
Panagiotis Bougioukos
  • 15,955
  • 2
  • 30
  • 47
8

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');
anion
  • 1,516
  • 1
  • 21
  • 35
Benjamin Barbé
  • 494
  • 6
  • 18
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

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

dc-p8
  • 784
  • 1
  • 6
  • 19
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

Koji D'infinte
  • 1,309
  • 12
  • 20
-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.

Vikhyath Maiya
  • 3,122
  • 3
  • 34
  • 68