Testing Services & HTTP
Services are simpler to test than components โ no template, no DOM. HTTP services need HttpClientTestingModule to mock requests. Pure logic services need only instantiation.
Testing simple services (no HTTP dependencies) is straightforward: instantiate and call methods.
// Pure logic service โ no dependencies
const service = new BiryaniService();
service.addBiryani({ name: "Test", price: 100 });
expect(service.getAll().length).toBe(1);"Service test = pure function test โ input do, output check karo."
For services with Angular dependencies, use TestBed:
TestBed.configureTestingModule({
providers: [BiryaniService]
});
const service = TestBed.inject(BiryaniService);Service tests are much faster than component tests because there is no template compilation.
For services that make HTTP calls, use HttpClientTestingModule and HttpTestingController.
import { HttpClientTestingModule, HttpTestingController }
from "@angular/common/http/testing";
let service: BiryaniService;
let httpMock: HttpTestingController;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [BiryaniService]
});
service = TestBed.inject(BiryaniService);
httpMock = TestBed.inject(HttpTestingController);
});"HttpClientTestingModule = fake server โ real request nahi jaata, mock response aata hai."
The HttpTestingController intercepts all HTTP requests and lets you assert on them.
Testing GET requests: Call the service method, expect the request, flush fake data.
it("should fetch biryanis", () => {
const mockData = [{ id: 1, name: "Hyderabadi", price: 500 }];
service.getBiryanis().subscribe(data => {
expect(data.length).toBe(1);
expect(data[0].name).toBe("Hyderabadi");
});
// Expect ONE request to /api/biryani
const req = httpMock.expectOne("/api/biryani");
expect(req.request.method).toBe("GET");
// Flush fake response โ triggers subscribe callback
req.flush(mockData);
// Verify no unmatched requests remain
httpMock.verify();
});"Expect request, check method, flush fake response, verify."
Testing POST, PUT, DELETE โ same pattern as GET, just different methods.
it("should create a biryani (POST)", () => {
const newBiryani = { name: "Hyderabadi", price: 500 };
service.createBiryani(newBiryani).subscribe(data => {
expect(data.id).toBe(1);
expect(data.name).toBe("Hyderabadi");
});
const req = httpMock.expectOne("/api/biryani");
expect(req.request.method).toBe("POST");
expect(req.request.body).toEqual(newBiryani); // Check body!
req.flush({ id: 1, ...newBiryani });
httpMock.verify();
});
it("should delete a biryani (DELETE)", () => {
service.deleteBiryani(1).subscribe(() => {
expect(true).toBeTrue(); // Just check it completes
});
const req = httpMock.expectOne("/api/biryani/1");
expect(req.request.method).toBe("DELETE");
req.flush(null); // DELETE often returns 204 with no body
httpMock.verify();
});"Same pattern: call service, expect request, check body/method, flush response."
ALWAYS call httpMock.verify() to catch unexpected requests.
Testing error handling: Simulate server errors with req.flush() with an error.
it("should handle 404 error", () => {
service.getBiryanis().subscribe({
next: () => fail("Should have failed!"),
error: (error) => {
expect(error.status).toBe(404);
expect(error.statusText).toBe("Not Found");
}
});
const req = httpMock.expectOne("/api/biryani");
req.flush("Not found", {
status: 404,
statusText: "Not Found"
});
httpMock.verify();
});Network error simulation:
it("should handle network error", () => {
service.getBiryanis().subscribe({
error: (error) => {
expect(error.status).toBe(0); // Network error = status 0
}
});
const req = httpMock.expectOne("/api/biryani");
req.error(new ProgressEvent("error")); // Simulate network failure
httpMock.verify();
});Always test BOTH success and error paths for every HTTP method.
Key Takeaways
- Pure logic services: instantiate directly, no TestBed needed
- HTTP services: use HttpClientTestingModule + HttpTestingController
- expectOne() catches the request, flush() sends fake response
- Always call httpMock.verify() at the end of each test
- Test both success and error paths using flush() with error config
Want to track your progress?
Log in to save your place and pick up where you left off.
Progress track karna chahte ho?
Login karo apni progress save karne ke liye aur jahan chhoda tha wahan se shuru karo.
Login