How to Mock Service in Angular Test: Simple Guide
To mock a service in an Angular test, provide a fake version of the service using
TestBed.configureTestingModule with useValue or useClass. Then, inject the mock service in your test to isolate component behavior without calling real service methods.Syntax
Use TestBed.configureTestingModule to replace the real service with a mock. You can provide a mock using useValue for an object with spy methods or useClass for a mock class.
providers: Array where you define service mocks.useValue: Supplies a simple object with mocked methods.useClass: Supplies a class that mimics the service.
typescript
TestBed.configureTestingModule({
providers: [
{ provide: RealService, useValue: mockService }
]
});Example
This example shows how to mock a service method using useValue with Jasmine spies. The component calls the mocked service method, and the test verifies the component uses the mock correctly.
typescript
import { TestBed } from '@angular/core/testing'; import { MyComponent } from './my.component'; import { MyService } from './my.service'; describe('MyComponent', () => { let component: MyComponent; let mockService: any; beforeEach(() => { mockService = { getData: jasmine.createSpy('getData').and.returnValue('mock data') }; TestBed.configureTestingModule({ providers: [ MyComponent, { provide: MyService, useValue: mockService } ] }); component = TestBed.inject(MyComponent); }); it('should use mocked service data', () => { const data = component.useService(); expect(mockService.getData).toHaveBeenCalled(); expect(data).toBe('mock data'); }); }); // my.component.ts export class MyComponent { constructor(private myService: MyService) {} useService() { return this.myService.getData(); } } // my.service.ts export class MyService { getData() { return 'real data'; } }
Output
PASS MyComponent should use mocked service data
Common Pitfalls
Common mistakes when mocking services include:
- Not providing the mock in
TestBed.configureTestingModule, so the real service is used. - Forgetting to spy on service methods, causing tests to call real implementations.
- Using
useClasswithout implementing all required methods, leading to runtime errors. - Not resetting spies between tests, causing false positives or negatives.
typescript
/* Wrong: No mock provided, real service used */ TestBed.configureTestingModule({ providers: [MyService] }); /* Right: Provide mock with spy */ const mockService = { getData: jasmine.createSpy().and.returnValue('mock') }; TestBed.configureTestingModule({ providers: [{ provide: MyService, useValue: mockService }] });
Quick Reference
Tips for mocking services in Angular tests:
- Use
useValuewith Jasmine spies for simple mocks. - Use
useClassfor more complex mock implementations. - Always inject the service via
TestBed.injector constructor. - Reset spies with
spy.calls.reset()if needed between tests. - Mock only what your test needs to keep tests fast and clear.
Key Takeaways
Mock services in Angular tests by providing fake versions with TestBed's useValue or useClass.
Use Jasmine spies to mock service methods and control their return values.
Always provide the mock in TestBed to avoid calling real service code during tests.
Reset spies between tests to prevent interference and ensure accurate results.
Keep mocks simple and focused on what the test requires for clarity and speed.