The tests check if the HTTP service works correctly by:
- Making fake API calls (GET/POST)
- Returning test data
- Handling errors properly
- All without using real internet connections
This ensures the service works as expected before using it in real apps.
data-http-service.ts
import { Injectable, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
const API_URL = 'https://api.example.com/data';
@Injectable({
providedIn: 'root'
})
export class DataHttpService {
http = inject(HttpClient);
getData(): Observable<unknown> {
return this.http.get<unknown>(API_URL);
}
postData(payload: unknown): Observable<unknown> {
return this.http.post<unknown>(API_URL, payload);
}
}
Production tip: Store API URLs in environment variables (never in code) and mock them for testing, complete walkthrough: Using and Mocking Angular Environments with Jest
data-http-service.spec.ts
import { TestBed } from '@angular/core/testing';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { DataHttpService } from './data-http.service';
describe('DataHttpService', () => {
let service: DataHttpService;
let httpMock: HttpTestingController;
const API_URL = 'https://api.example.com/data';
const mockData = { id: 1, name: 'Test Data' };
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [DataHttpService]
});
service = TestBed.inject(DataHttpService);
httpMock = TestBed.inject(HttpTestingController);
});
afterEach(() => {
httpMock.verify(); // Verify no outstanding requests
});
it('should be created', () => {
expect(service).toBeTruthy();
});
describe('.getData', () => {
it('should make GET request and return data', () => {
service.getData().subscribe(data => {
expect(data).toEqual(mockData);
});
const req = httpMock.expectOne(API_URL);
expect(req.request.method).toEqual('GET');
req.flush(mockData);
});
it('should handle GET errors', () => {
const mockError = { status: 404, statusText: 'Not Found' };
service.getData().subscribe({
next: () => fail('Should have failed'),
error: (error) => {
expect(error.status).toEqual(mockError.status);
}
});
const req = httpMock.expectOne(API_URL);
req.flush(null, mockError);
});
});
describe('.postData', () => {
it('should make POST request with payload', () => {
const testPayload = { data: 'test' };
service.postData(testPayload).subscribe(data => {
expect(data).toEqual(mockData);
});
const req = httpMock.expectOne(API_URL);
expect(req.request.method).toEqual('POST');
expect(req.request.body).toEqual(testPayload);
req.flush(mockData);
});
it('should handle POST errors', () => {
const testPayload = { data: 'test' };
const mockError = { status: 500, statusText: 'Server Error' };
service.postData(testPayload).subscribe({
next: () => fail('Should have failed'),
error: (error) => {
expect(error.status).toEqual(mockError.status);
}
});
const req = httpMock.expectOne(API_URL);
req.flush(null, mockError);
});
});
});
Top comments (2)
I followed the series of articles and it's great! Just one comment, because many people come and copy things literally without thinking much xD (or without adapting them to their specific case).
When you copy this, the API_URL constant in this case is defined both in the service and in the test file. This works, but if the URL changes, you must remember to update it in both places.
So, when you apply this, you could export the constant from the service file (export const API_URL = ...;) and import it into the test file. This ensures you always use the same URL.
Also, keeping it separate in the tests can also be useful if you need to test different endpoints in the future within the same spec file (although in that case you could import more than one)
Remember to evaluate and think critically according to your case (You can even have a file with the API URLs).
To the author of the post, thank you for taking the time to make them and share :)
Thanks @damiansiredev !
You inspired a deep dive into Angular environment variables covering secure configuration, CI/CD integration, and proper mocking for unit tests:
Using and Mocking Angular Environments with Jest