Swiftorial Logo
Home
Swift Lessons
Matchups
CodeSnaps
Tutorials
Career
Resources

HTTP Client Testing

Testing HTTP requests in Angular is crucial to ensure the reliability of your application. This guide covers the basics of testing HTTP requests using Angular's HTTP Client and the HttpTestingController.

Setting Up HTTPClientModule

First, import the HttpClientModule into your app module:

// app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';
import { AppComponent } from './app.component';
import { DataService } from './data.service';
import { HomeComponent } from './home/home.component';

@NgModule({
  declarations: [AppComponent, HomeComponent],
  imports: [BrowserModule, HttpClientModule],
  providers: [DataService],
  bootstrap: [AppComponent]
})
export class AppModule { }

Creating a Service

Next, create a service to manage HTTP requests using the Angular CLI command:

$ ng generate service data

This command generates a new service file named data.service.ts.

Implementing the Service

In the service file, inject the HttpClient and create methods to perform HTTP requests:

// data.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class DataService {
  private apiUrl = 'https://jsonplaceholder.typicode.com/posts';

  constructor(private http: HttpClient) { }

  getPosts(): Observable {
    return this.http.get(this.apiUrl);
  }

  addPost(post: any): Observable {
    return this.http.post(this.apiUrl, post);
  }
}

Setting Up Testing Module

Import the HttpClientTestingModule and HttpTestingController into your test file:

// data.service.spec.ts
import { TestBed } from '@angular/core/testing';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { DataService } from './data.service';

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

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [HttpClientTestingModule],
      providers: [DataService]
    });

    service = TestBed.inject(DataService);
    httpMock = TestBed.inject(HttpTestingController);
  });

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

  it('should retrieve posts', () => {
    const dummyPosts = [
      { userId: 1, id: 1, title: 'Post 1', body: 'Body 1' },
      { userId: 1, id: 2, title: 'Post 2', body: 'Body 2' }
    ];

    service.getPosts().subscribe(posts => {
      expect(posts.length).toBe(2);
      expect(posts).toEqual(dummyPosts);
    });

    const req = httpMock.expectOne(service['apiUrl']);
    expect(req.request.method).toBe('GET');
    req.flush(dummyPosts);
  });

  it('should add a post', () => {
    const newPost = { userId: 1, title: 'Post 3', body: 'Body 3' };

    service.addPost(newPost).subscribe(post => {
      expect(post).toEqual(newPost);
    });

    const req = httpMock.expectOne(service['apiUrl']);
    expect(req.request.method).toBe('POST');
    req.flush(newPost);
  });
});

Using the Testing Module

Inject the DataService and HttpTestingController into your tests to simulate HTTP requests and verify the expected behavior:

// data.service.spec.ts
import { TestBed } from '@angular/core/testing';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { DataService } from './data.service';

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

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [HttpClientTestingModule],
      providers: [DataService]
    });

    service = TestBed.inject(DataService);
    httpMock = TestBed.inject(HttpTestingController);
  });

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

  it('should retrieve posts', () => {
    const dummyPosts = [
      { userId: 1, id: 1, title: 'Post 1', body: 'Body 1' },
      { userId: 1, id: 2, title: 'Post 2', body: 'Body 2' }
    ];

    service.getPosts().subscribe(posts => {
      expect(posts.length).toBe(2);
      expect(posts).toEqual(dummyPosts);
    });

    const req = httpMock.expectOne(service['apiUrl']);
    expect(req.request.method).toBe('GET');
    req.flush(dummyPosts);
  });

  it('should add a post', () => {
    const newPost = { userId: 1, title: 'Post 3', body: 'Body 3' };

    service.addPost(newPost).subscribe(post => {
      expect(post).toEqual(newPost);
    });

    const req = httpMock.expectOne(service['apiUrl']);
    expect(req.request.method).toBe('POST');
    req.flush(newPost);
  });
});

Handling Errors in Tests

To handle errors in your HTTP requests during testing, use the flush method with an error response:

// data.service.spec.ts
it('should handle error response', () => {
  service.getPosts().subscribe(
    () => fail('expected an error, not posts'),
    error => expect(error.message).toContain('test 404 error')
  );

  const req = httpMock.expectOne(service['apiUrl']);
  req.flush('test 404 error', { status: 404, statusText: 'Not Found' });
});

Key Points

  • Testing HTTP requests in Angular is crucial to ensure the reliability of your application.
  • Import HttpClientTestingModule and HttpTestingController to set up the testing environment.
  • Create a service to handle HTTP requests using the HttpClient.
  • Simulate HTTP requests and verify expected behavior using HttpTestingController.
  • Handle errors in your tests using the flush method with an error response.

Conclusion

Testing HTTP requests is an essential part of ensuring the reliability and robustness of your Angular applications. By using the HttpClientTestingModule and HttpTestingController, you can effectively test your HTTP requests and handle errors. Happy coding!