Testing
Every ng generate component has quietly created a .spec.ts file alongside each component (Chapter 1) — those are tests, and this chapter finally puts them to use. Angular's testing stack uses Jasmine (the test framework: describe/it/expect) run by Karma (the test runner, executing tests in a real browser), with TestBed as Angular's own utility for creating components in a test environment.
it() for React's test(), jasmine.createSpy() for vi.fn() — but the goals are identical: render a component, simulate interaction, assert on what the user would see. If that chapter made sense, this one will feel familiar despite the different tool names.
A Test for a Service — The Simplest Case
describe groups related tests; it defines one; beforeEach runs before each test for fresh setup; expect(...).toBe(...) asserts. TestBed.inject(CounterService) retrieves the service through the same DI system the real app uses (Chapter 6), rather than constructing it manually — so the test exercises it exactly as it'd be used in practice.
Testing a Component with TestBed
TestBed.createComponent returns a fixture — a handle to the live component plus its rendered DOM (fixture.nativeElement). The key Angular-specific detail is fixture.detectChanges(): unlike React Testing Library, which re-renders automatically, an Angular test must explicitly trigger change detection to render the initial view and to update it after a state change. Forgetting it is the most common reason an Angular test sees stale, un-updated DOM.
Mocking a Dependency
Dependency injection makes testing easier: a component asks for UserService, and the test simply provides a fake one instead via { provide: UserService, useValue: fakeUserService }. The component is none the wiser — it gets whatever DI supplies. This means a component can be tested in isolation, with a fake service returning fixed data, without ever hitting a real API — the same goal as React's mock functions (Advanced Chapter 4), achieved through DI rather than passing mocks as props.
fixture.detectChanges() first — after creating the component (to render the initial view) and after any action that changes state (to re-render). React Testing Library handles this automatically, so it's an easy habit to miss when coming from that background. If a test sees an empty or unchanged DOM, a missing detectChanges() is the first thing to check.
| Angular (Jasmine/TestBed) | React (Vitest/RTL) |
|---|---|
| describe / it / expect | describe / test / expect |
| TestBed.createComponent | render(...) |
| fixture.nativeElement.querySelector | screen.getByRole / getByText |
| fixture.detectChanges() | (automatic) |
| jasmine.createSpy() | vi.fn() |
| { provide, useValue } mock | Mock passed as a prop |
Running the Tests
ng test runs the whole suite, opening a browser Karma controls to execute the tests in, and re-running automatically as files change — the equivalent of a test runner's watch mode. The default starter project already passes its one generated AppComponent test, so ng test works from the very first ng new.
Coding Challenges
Write a spec for a CounterService (with increment/decrement/reset) using TestBed.inject, asserting the count behaves correctly after each operation.
📄 View solutionWrite a component spec using TestBed.createComponent that clicks the +1 button and asserts the rendered text updates — remembering detectChanges() after creation and after the click.
📄 View solutionWrite a spec for a component that depends on a UserService, providing a fake service (via { provide, useValue }) returning fixed data, and assert the component renders that fake data without any real HTTP call.
📄 View solutionChapter 14 Quick Reference
- Jasmine — the test framework (
describe/it/expect/beforeEach); Karma — the runner - TestBed.inject(Service) — gets a service through DI for testing
- TestBed.createComponent → a fixture (live component +
nativeElementDOM) - fixture.detectChanges() — manually trigger render; required after creation and state changes
- Mock a dependency with { provide: Service, useValue: fake } — DI makes isolation easy
- ng test — runs the suite in watch mode via Karma
- Same goals as React Testing Library; different tool names (
it=test,createSpy=vi.fn)