DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’» is a community of 963,274 amazing developers

We're a place where coders share, stay up-to-date and grow their careers.

Create account Log in
Rudolf Olah
Rudolf Olah

Posted on

Angular Testing Nested Components and Components that Rely or Use Other Components in Their Templates

You have two Angular components:

  • HomeComponent
  • HelloComponent

The template for HomeComponent looks like this:

<h1>Hello!</h1>
<app-hello name="Rudolf"></app-hello>

The component definition for HelloComponent looks like this:

@Component({
  selector: 'app-hello',
  // ...
)
export class HelloComponent {
  @Input() name;
}

When you try and test the HomeComponent, there will be errors because you need to include the HelloComponent in the TestBed configuration.

You will have to stub out the nested component and that should look like this:

@Component({ selector: 'app-hello', template: '' })
class HelloStubComponent implements Partial<HelloComponent> {
  @Input() name;
}

Then in the TestBed configuration you will have something like this:

TestBed.configureTestingModule({
  declarations: [
    HomeComponent,
    HelloStubComponent
  ]
}).compileComponents();

To make things more convenient, you can include the definition of the stub component within your component file:

// hello.component.ts
const selector = 'app-hello';
@Component({
  selector,
  // ...
)
export class HelloComponent {
  @Input() name;
}
@Component({ selector, template: '' })
export class HelloStubComponent implements Partial<HelloComponent> {
  @Input() name;
}

When compiling your Angular app, the module will declare HelloComponent. When running your tests, the test bed module configuration will declare HelloStubComponent.

You can use Partial<T>, a utility type from TypeScript to ensure that your stubbed component matches the interface of the actual component class.

By keeping the stub definition close to the actual component class, you can re-use the stub in multiple tests.

Stubs and Stub Providers for Services in Angular

For a service, you can do something similar:

// world-service.ts
@Injectable({ providedIn: 'root' })
export class WorldService {}

export class WorldServiceStub {}
export const worldServiceStubProvider = {
  provide: WorldService,
  useFactory: () => new WorldServiceStub()
}

Then in your tests you can setup the TestBed like this:

import { worldServiceStubProvider } from 'path/to/world-service.ts';
// ...
TestBed.configureTestingModule({
  // ...
  providers: [ worldServiceStubProvider ]
});

// and then you can use the following to get the reference to the stub provider from the TestBed:
TestBed.get(WorldService);

Top comments (0)

🌚 Browsing with dark mode makes you a better developer by a factor of exactly 40.

It's a scientific fact.