Your 6-hour struggle is exactly why I built @halverscheid-fiae.de/angular-testing-factory! 🚀
Your core issue is mock setup complexity - you're spending more time fighting mocks than testing logic. Here's how the library solves this:
// Manual HttpClient mock hell
beforeEach(async () => {
mockCoreService = MockService(CoreService);
// + HttpClientTestingModule import
// + Manual spy setup
// + Mock return value configuration
// + Prayer that it works 🙏
});
beforeEach(async () => {
await TestBed.configureTestingModule({
providers: [
provideHttpClientMock({
post: jest.fn(() => of({ message: 'Registration successful!', status: 'success' }))
}),
// Your CoreService will automatically use the mocked HttpClient
]
}).compileComponents();
});
HttpClientTestingModule
setupsatisfies jest.Mocked<Partial<T>>
prevents mock driftCoreService
automatically gets the mocked HttpClient
it('should submit form successfully', fakeAsync(() => {
// Form setup (unchanged)
component.contactFormGroup.setValue({
username: 'testuser',
fullname: 'Test User',
email: '[email protected]',
password: 'TestPass123!'
});
// Test execution (unchanged)
component.submitForm(new Event('submit'));
tick(100);
// Assertions work because HttpClient is properly mocked
const httpClientMock = TestBed.inject(HttpClient);
expect(httpClientMock.post).toHaveBeenCalledWith(
'http://localhost:3000/register',
expect.any(Object),
expect.any(Object)
);
}));
// TypeScript catches mock inconsistencies at compile-time!
const provideMyServiceMock = createServiceProviderFactory(MyService, {
registerUser: jest.fn(() => of(mockResponse)),
// ↑ TypeScript validates this matches your real service
} satisfies jest.Mocked<Partial<MyService>>);
npm install --save-dev @halverscheid-fiae.de/angular-testing-factory
// Replace your entire beforeEach setup with:
import { provideHttpClientMock } from '@halverscheid-fiae.de/angular-testing-factory';
TestBed.configureTestingModule({
providers: [provideHttpClientMock()]
});
Result: 80% less boilerplate, 100% more reliable tests!
provideRouterMock()
provideActivatedRouteMock({ params: of({ id: '1' }) })
provideFormBuilderMock()
provideAngularCoreMocks({ httpClient: true, router: true })
P.S. - Your 6 hours of frustration inspired this exact use case in the library! 😅
The goal is simple: Write tests, not mock configuration.
Hope this saves you (and others) those painful mock-setup hours! 🎉