When you create components, services, or pipes with the ng command in Angular, a spec file is usually generated for testing (unless you opt out). In long-running projects, though, tests may fail—or people delete spec files just to force tests to pass. That has happened in some of my older projects too.
I wanted AI to generate the initial files, so I wrote this guideline mainly to feed it to generative AI.
STEP BY STEP
1. Find components, services, and pipes without spec files and list them
Spec files use names related to the file under test, as follows.
| File type | Source file | Spec file |
|---|---|---|
| Component | example.component.ts |
example.component.spec.ts |
| Ionic page component | example.page.ts |
example.page.spec.ts |
| Service | example.service.ts |
example.service.spec.ts |
| Pipe | example.pipe.ts |
example.pipe.spec.ts |
| Directive | example.directive.ts |
example.directive.spec.ts |
Spec files should sit next to the source file. First, recursively scan all test targets and list any that do not have a spec file in the same directory.
2. Create spec files
Component
The rules are the same for Angular components and Ionic page components. For ExampleComponent, use:
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ExampleComponent } from './example.component';
describe('ExampleComponent', () => {
let component: ExampleComponent;
let fixture: ComponentFixture<ExampleComponent>;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ExampleComponent],
});
fixture = TestBed.createComponent(ExampleComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
For ExamplePage, only ExampleComponent becomes ExamplePage. Simple. The Angular CLI template is here:
Service
For ExampleService, use:
import { TestBed } from '@angular/core/testing';
import { ExampleService } from './example.service';
describe('ExampleService', () => {
let service: ExampleService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(ExampleService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
The Angular CLI template is here:
Pipe
For ExamplePipe, use:
import { ExamplePipe } from './example.pipe';
describe('ExamplePipe', () => {
it('create an instance', () => {
const pipe = new ExamplePipe();
expect(pipe).toBeTruthy();
});
});
The Angular CLI template is here:
Directive
For ExampleDirective, use:
import { ExampleDirective } from './example.directive';
describe('ExampleDirective', () => {
it('should create an instance', () => {
const directive = new ExamplePipe();
expect(directive).toBeTruthy();
});
});
The Angular CLI template is here:
3. Match your project conventions
In my experience, most projects define dependencies and test mocks in one place and pass them to configureTestingModule. In my case, I create test.config.ts with settings I want across tests:
export const testConfig: ApplicationConfig = {
providers: [
provideFirebaseApp(() => initializeApp(environment.firebase)),
provideAuth(() => getAuth()),
...
Then configure it in configureTestingModule like this:
beforeEach(() => {
TestBed.configureTestingModule({
providers: testConfig.providers,
});
...
If your project has baseline rules, check other spec files and align with those conventions.
Summary
As you can tell, I wrote this article because I did not want to paste the whole thing into a small prompt window and throw it away. Try turning reusable AI coding instructions into articles and sharing them.
See you next time.