Testing Angular Components with Services using Jest
Mock services in component tests to isolate behavior, control responses, and validate interactions without testing the service itself. This keeps tests fast, focused, and free from external dependencies. another-component.ts import { Component, inject } from '@angular/core'; import { MySuperService } from '../my-super.service'; @Component({ selector: 'app-another', template: `My message: {{message}}`, }) export class AnotherComponent { mySuperService = inject(MySuperService); message = ''; showMessage() { this.message = this.mySuperService.getMessage(); } } another-component.spec.ts import { ComponentFixture, TestBed } from '@angular/core/testing'; import { AnotherComponent } from './another.component'; import { MySuperService } from '../my-super.service'; import { By } from '@angular/platform-browser'; describe('AnotherComponent', () => { let component: AnotherComponent; let fixture: ComponentFixture; const mockMySuperServiceMock = { getMessage: jest.fn().mockReturnValue('Super message') }; beforeEach(() => { TestBed.configureTestingModule({ declarations: [AnotherComponent], providers: [ { provide: MySuperService, useValue: mockMySuperService }, ] }); fixture = TestBed.createComponent(AnotherComponent); component = fixture.componentInstance; fixture.detectChanges(); }); it('should create', () => { expect(component).toBeTruthy(); }); describe ('.showMessage', () => { it('should show the message', () => { expect(mockMySuperService.getMessage).not.toHaveBeenCalled(); expect(component.message).toBe(''); component.showMessage(); expect(mockMySuperService.getMessage).toHaveBeenCalledTimes(1); expect(component.message).toBe('Super message'); }); it('should display message in template', () => { component.showMessage(); fixture.detectChanges(); const messageEl = fixture.debugElement.query(By.css('p.message')); expect(messageEl.nativeElement.textContent).toContain('Super message'); }); }); });

Mock services in component tests to isolate behavior, control responses, and validate interactions without testing the service itself. This keeps tests fast, focused, and free from external dependencies.
another-component.ts
import { Component, inject } from '@angular/core';
import { MySuperService } from '../my-super.service';
@Component({
selector: 'app-another',
template: ``
,
})
export class AnotherComponent {
mySuperService = inject(MySuperService);
message = '';
showMessage() {
this.message = this.mySuperService.getMessage();
}
}
another-component.spec.ts
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { AnotherComponent } from './another.component';
import { MySuperService } from '../my-super.service';
import { By } from '@angular/platform-browser';
describe('AnotherComponent', () => {
let component: AnotherComponent;
let fixture: ComponentFixture<AnotherComponent>;
const mockMySuperServiceMock = {
getMessage: jest.fn().mockReturnValue('Super message')
};
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [AnotherComponent],
providers: [
{ provide: MySuperService, useValue: mockMySuperService },
]
});
fixture = TestBed.createComponent(AnotherComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
describe ('.showMessage', () => {
it('should show the message', () => {
expect(mockMySuperService.getMessage).not.toHaveBeenCalled();
expect(component.message).toBe('');
component.showMessage();
expect(mockMySuperService.getMessage).toHaveBeenCalledTimes(1);
expect(component.message).toBe('Super message');
});
it('should display message in template', () => {
component.showMessage();
fixture.detectChanges();
const messageEl = fixture.debugElement.query(By.css('p.message'));
expect(messageEl.nativeElement.textContent).toContain('Super message');
});
});
});