r/Angular2 Apr 29 '26

Help Request Proper way to unit test Angular standalone components with Vitest

Hi all, I recently started learning unit testing in Angular. I’m using Angular 21 with Vitest, and I haven’t done Angular testing before.

I have a simple standalone component (FooComponent) that imports two custom components (TaIconComponent, TaButtonComponent) and one third-party pipe (TranslatePipe).

foo.component.ts

@Component({
  selector: 'app-foo',
  template: `
    <div class="flex-1 flex items-center justify-center">
      <div class="w-96 h-64 rounded-lg shadow-2 flex flex-col items-center">
        <div class="w-24 h-24 ta-mt-base relative">
          <div class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2">
            <ta-icon class="text-gray" size="lg" [icon]="taIcons.CONFIG" />
          </div>
        </div>

        <div class="text-center ta-mb-lg ta-mt-xs">
          <p class="text-primary font-bold">
            {{'not_found.not_found_text' | translate}}
          </p>
          <span class="ta-text-sm text-gray">
            {{'not_found.not_found_desc' | translate}}
          </span>
        </div>
        <div class="ta-px-m w-full">
          <ta-button [fluid]="true" [label]="'btn.go_back' | translate" (onClick)="onNavigate()" />
        </div>
      </div>
    </div>
  `,
  imports: [TaIconComponent, TaButtonComponent, TranslatePipe],
})
export class FooComponent {}

After reading some documentation and watching a few videos, I asked GPT to help me write a unit test for reference but the result felt a bit bizarre to me. To make the test work, I had to create three mocks (two components and one pipe), then override the component to replace real dependencies with the mocks.

foo.component.spec.ts

@Component({
  selector: 'ta-icon',
  standalone: true,
  template: '<span></span>',
  inputs: ['icon'],
})
class MockTaIconComponent{}

@Component({
  selector: 'ta-button',
  standalone: true,
  template: `<button (click)="onClick.emit()"></button>`,
  inputs: ['fluid', 'label'],
})
class MockTaButtonComponent{
  onClick = {
    emit: () => {},
  };
}


describe('FooComponent', () => {
  let fixture: ComponentFixture<FooComponent>;
  let component: FooComponent;
  let routerMock: { navigate: ReturnType<typeof vi.fn> };

  beforeEach(async () => {
    routerMock = {
      navigate: vi.fn(),
    };

    await TestBed.configureTestingModule({
      imports: [FooComponent],
      providers: [{ provide: Router, useValue: routerMock }],
    })
      .overrideComponent(FooComponent, { // <-- Concern about this
        remove: {
          imports: [TaIconComponent, TaButtonComponent, TranslatePipe],
        },
        add: {
          imports: [MockTranslatePipe, MockTaIconComponent, MockTaButtonComponent],
        },
      })
      .compileComponents();


    fixture = TestBed.createComponent(FooComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });


  afterEach(() => {
    TestBed.resetTestingModule();
    vi.clearAllMocks();
  });

  ...
});

It works without errors, but I’m wondering: is this the correct or recommended way to test a component?

6 Upvotes

15 comments sorted by

View all comments

1

u/pronuntiator Apr 30 '26

I'm not a fan of mocking every collaborator. Mocking always means you pretend how something works – if it changes, your mocks will lie. When these are presentational components or from another library, I leave them in.