angular/components · error · Error

MatTestDialogOpener does not have a component provided.

Error message

MatTestDialogOpener does not have a component provided.

What it means

MatTestDialogOpener is a test utility injected as a dialog 'opener' component; its static component field must be configured via withComponent(...) before it is instantiated. The constructor throws if no dialog component class was provided, because it would otherwise have nothing to open. It guards against using the test opener without the static withComponent() setup call.

Source

Thrown at src/material/dialog/testing/dialog-opener.ts:52

  closedResult: R | undefined;

  private readonly _afterClosedSubscription: Subscription;

  private readonly _ngZone = inject(NgZone);

  /** Static method that prepares this class to open the provided component. */
  static withComponent<T = unknown, R = unknown>(
    component: ComponentType<T>,
    config?: MatDialogConfig,
  ) {
    MatTestDialogOpener.component = component;
    MatTestDialogOpener.config = config;
    return MatTestDialogOpener as ComponentType<MatTestDialogOpener<T, R>>;
  }

  constructor() {
    if (!MatTestDialogOpener.component) {
      throw new Error(`MatTestDialogOpener does not have a component provided.`);
    }

    this.dialogRef = this._ngZone.run(() => {
      const config = {...(MatTestDialogOpener.config || {})};
      config.enterAnimationDuration = 0;
      config.exitAnimationDuration = 0;
      return this.dialog.open<T, R>(MatTestDialogOpener.component as ComponentType<T>, config);
    });
    this._afterClosedSubscription = this.dialogRef.afterClosed().subscribe(result => {
      this.closedResult = result;
    });
  }

  ngOnDestroy() {
    this._afterClosedSubscription.unsubscribe();
    MatTestDialogOpener.component = undefined;
    MatTestDialogOpener.config = undefined;
  }

View on GitHub (pinned to 0411926e7d)

Solutions

  1. Call MatTestDialogOpener.withComponent(MyDialogContent) before providing/injecting the opener in the test
  2. Use DialogTestModule.withDialogs(...) or the documented setup so withComponent is invoked during TestBed configuration
  3. Ensure each test that injects the opener re-applies withComponent if configuration is reset between tests
  4. Alternatively use DialogHarness directly instead of MatTestDialogOpener

Example fix

// before
TestBed.configureTestingModule({ providers: [MatTestDialogOpener] });
const opener = TestBed.inject(MatTestDialogOpener);
// after
TestBed.configureTestingModule({
  providers: [MatTestDialogOpener.withComponent(DialogContentComponent)],
});
const opener = TestBed.inject(MatTestDialogOpener);
Defensive patterns

Strategy: validation

Validate before calling

if (!MatTestDialogOpener.component) {
  throw new Error('Call MatTestDialogOpener.withComponent(MyDialogComponent) before injecting the opener');
}
const opener = TestBed.inject(MatTestDialogOpener);

Try / catch

try {
  opener = TestBed.inject(MatTestDialogOpener);
} catch (e) {
  if (String(e?.message).includes('does not have a component provided')) {
    fail('MatTestDialogOpener.withComponent() was not called in TestBed setup');
  }
  throw e;
}

Prevention

When it happens

Trigger: Providing MatTestDialogOpener in a test module (e.g. via DialogTestModule or providers) without ever calling MatTestDialogOpener.withComponent(MyDialogComponent) beforehand; ordering issue where the injector instantiates the opener before withComponent runs; using the opener from a shared test module where another test reset configuration.

Common situations: Setting up dialog component harness tests and skipping the withComponent step; copying provider setup from docs but not the withComponent call; multiple beforeEach ordering problems causing the opener to be created before configuration.

Related errors


AI-assisted analysis of angular/components@0411926e7d (2026-08-31). Data as JSON: /api/errors/dd2297289b0b5b78. Report an issue: GitHub.