
The Missing Ingredient for Angular Template Code Coverage and Future-Proof Testing

š§ What's wrong with JIT?
ā° Why now?
š Other Benefits of AOT Testing
ā”ļø Faster Test Execution
šÆ Production-Symmetry
š® Future-Proof Tests
š¤ Drawbacks
šŖ Dynamic Component Constructs Should Be Avoided
// š This is broken with AOT.
const fixture = render(`<app-button/>`, { imports: [Button] });
function render(template, { imports }) {
@Component({
template,
imports,
})
class TestContainer {}
return TestBed.createComponent(TestContainer);
}
function render(template, { imports }) {
@Component({
jit: true,
template,
imports,
})
class TestContainer {}
return TestBed.createComponent(TestContainer);
}
š¦¦ Shallow Testing is More Challenging
TestBed#overrideComponent
// app.cmp.spec.ts
vi.mock('./street-map.cmp', async () => {
return {
StreetMap: await import('./street-map-fake.cmp').then(
(m) => m.StreetMapFake
),
};
});
// street-map-fake.cmp.ts
@Component({
selector: 'app-street-map',
template: 'Fake Street Map',
})
class StreetMapFake implements StreetMap {
// ...
}
TestBed#overrideComponent
*.jit.spec.ts
šØš»āš³ Taking Vitest with AOT for a Spin
1. Set up Vitest
2. Enable AOT
vite.config.js
export default defineConfig({
...
plugins: [
angular({ jit: false }),
...
],
...
});
š Configure Code Coverage
istanbul
v8
istanbul
1. Install @vitest/coverage-istanbul
@vitest/coverage-istanbul
npm install -D @vitest/coverage-istanbul
2. Choose istanbul
as your coverage provider
istanbul
vite.config.mts
export default defineConfig({
...
test: {
...
coverage: {
provider: 'istanbul',
},
},
});
š¬ Watch it in Action
nx test my-app --coverage --ui --watch
# or
ng test --coverage --ui --watch