← All articles

Step by Step: Regenerating Angular spec Files

A step-by-step guide to finding missing Angular spec files and recreating them from CLI templates, then aligning them with your project's test setup.

Published
Step by Step: Regenerating Angular spec Files cover image

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:

https://github.com/angular/angular-cli/blob/main/packages/schematics/angular/component/files/__name%40dasherize%40if-flat__/__name%40dasherize__.__type%40dasherize__.spec.ts.templatehttps://github.com/angular/angular-cli/blob/main/packages/schematics/angular/component/files/__name%40dasherize%40if-flat__/__name%40dasherize__.__type%40dasherize__.spec.ts.template

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:

https://github.com/angular/angular-cli/blob/main/packages/schematics/angular/service/files/__name%40dasherize__.__type%40dasherize__.spec.ts.templatehttps://github.com/angular/angular-cli/blob/main/packages/schematics/angular/service/files/__name%40dasherize__.__type%40dasherize__.spec.ts.template

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:

https://github.com/angular/angular-cli/blob/main/packages/schematics/angular/pipe/files/__name%40dasherize____typeSeparator__pipe.spec.ts.templatehttps://github.com/angular/angular-cli/blob/main/packages/schematics/angular/pipe/files/__name%40dasherize____typeSeparator__pipe.spec.ts.template

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:

https://github.com/angular/angular-cli/blob/main/packages/schematics/angular/directive/files/__name%40dasherize__.__type%40dasherize__.spec.ts.templatehttps://github.com/angular/angular-cli/blob/main/packages/schematics/angular/directive/files/__name%40dasherize__.__type%40dasherize__.spec.ts.template

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.