Unit Testing Components
Component tests verify creation, template rendering, user interactions, and service integration. Test through public API โ what the USER sees and does.
When testing a component, focus on what the component DOES, not how it does it. These are the key questions:
- Does it create successfully? โ catches import/provider errors
- Does it display correct data? โ template rendering with correct values
- Does it handle user interactions? โ clicks, inputs, form submissions
- Does it call services correctly? โ service methods invoked with right params
"Test = sawaal โ banata hai? dikhata hai? click handle karta hai? service call karta hai?"
Test through the PUBLIC API: set @Inputs, trigger events, read DOM output. Never test private methods directly.
The simplest test โ verify the component creates without errors. This catches import issues, missing providers, and constructor errors.
it("should create the component", () => {
expect(component).toBeTruthy();
});"Pehla test โ ban raha hai ya nahi, bas itna check karo."
What this catches:
- Missing imports in TestBed config
- Missing providers for injected services
- Syntax errors in the component class
- Template compilation errors
Always start with this test. If creation fails, nothing else works.
Testing template content: After calling detectChanges(), query the DOM and check rendered values.
it("should display biryani name", () => {
fixture.detectChanges(); // Render template
const h1 = fixture.nativeElement.querySelector("h1");
expect(h1.textContent).toContain("Hyderabadi");
});
it("should display all items", () => {
fixture.detectChanges();
const items = fixture.nativeElement.querySelectorAll(".biryani-item");
expect(items.length).toBe(3);
});"DOM query karo, text check karo, count check karo."
Use fixture.nativeElement like regular DOM โ querySelector, querySelectorAll, textContent, etc.
Testing user interactions: Simulate clicks, inputs, and form submissions, then check the result.
it("should order biryani on button click", () => {
const button = fixture.nativeElement.querySelector("#order-btn");
button.click(); // Trigger click event
fixture.detectChanges(); // Update after click
expect(component.orderPlaced()).toBeTrue();
});
// Using DebugElement (alternative approach):
it("should filter items on input", () => {
const input = fixture.debugElement.query(By.css("#search"));
input.nativeElement.value = "Hyderabadi";
input.nativeElement.dispatchEvent(new Event("input"));
fixture.detectChanges();
expect(component.filteredItems().length).toBe(1);
});"Click karo, detectChanges karo, result check karo."
fixture.nativeElement.querySelector() is simpler. fixture.debugElement.query(By.css()) is the older Angular testing way.
Mocking services is essential โ never call real APIs in tests. Use jasmine.createSpyObj to create mock services.
// Create mock service with spy methods
const mockBiryaniService = jasmine.createSpyObj("BiryaniService", [
"getBiryanis", "createBiryani", "deleteBiryani"
]);
// Make getBiryanis return fake data
mockBiryaniService.getBiryanis.and.returnValue(
of([{ name: "Hyderabadi", price: 500 }])
);
// Provide mock in TestBed
TestBed.configureTestingModule({
providers: [
{ provide: BiryaniService, useValue: mockBiryaniService }
]
});"Mock = duplicate service โ real API call nahi, fake data do."
Spy methods also track calls: expect(mockService.getBiryanis).toHaveBeenCalled().
Key Takeaways
- Test creation first โ catches import/provider errors
- fixture.detectChanges() renders template โ query DOM after calling it
- Query elements with fixture.nativeElement.querySelector()
- Simulate clicks with element.click() then detectChanges()
- Mock services with jasmine.createSpyObj โ never call real APIs in tests
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