es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Probando componente Angular que extiende una clase abstracta.

Tengo esta configuración para varios componentes:

@Directive()
export abstract class BaseComponent implements OnInit {

@Select(PortalState.portal) public portalState: Observable;
public portal: PortalModel;
protected ngUnsubscribe: Subject = new Subject();

constructor(
protected someService: SomeService,
protected route: ActivatedRoute
){
}

public ngOnInit(): void {
this.route.params
.pipe(
filter(res => !!res),
tap(res => this.id = res[‘id’]),
switchMap(() => this.portalState),
takeUntil(this.ngUnsubscribe)
)
.subscribe(res => {
this.portal = res;
this.afterInit();
});
}

public ngOnDestroy(): void {
this.ngUnsubscribe.next();
this.ngUnsubscribe.complete();
}

public abstract afterInit(): void
}

y luego en cada componente que extiende esta clase base:

@Component({…})
export class SomeComponent extends BaseComponent {

public specificVar: any;

constructor(
protected someService: SomeService,
protected route: ActivatedRoute
){
super(someService, route);
}

public afterInit(): void {
/** hacer cosas específicas del componente */
this.specificVar = ‘algo’;
}

}

Ahora funciona bien, sin embargo, al probar, parece que el método ngOnInit del componente abstracto no se llama en absoluto, lo que provoca (en este ejemplo) que la variable “specificVar” sea undefined.

El archivo spec parece bastante tradicional:

let store: Store; /** Ngxs store */
const mockPortalModel: PortalModel = {id: 1};

beforeEach(async () => {
TestBed.configureTestingModule(/** providers y configuración habitual */);
store = TestBed.inject(Store);
store.reset({
portalState: mockPortalModel
});
jest.spyOn(store, ‘dispatch’);
jest.spyOn(store, ‘select’);
});

beforeEach(() => {
fixture = TestBed.createComponent(SomeComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

¿Alguna idea de por qué ngOnInit y posteriormente afterInit no se están llamando?

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    El problema con el código anterior es que el gancho del ciclo de vida ngOnInit no se está llamando al probar los componentes. Una solución posible es activar manualmente el gancho ngOnInit llamando al método fixture.detectChanges() justo después de crear la instancia del componente en el bloque beforeEach del archivo de prueba. Aquí tienes una versión actualizada del bloque beforeEach:

    beforeEach(() => {
      fixture = TestBed.createComponent(SomeComponent);
      component = fixture.componentInstance;
      jest.spyOn(component, 'ngOnInit').mockImplementation(() => {
        component.portalState = store.selectSnapshot(PortalState.portal);
        component.ngOnInit();
      });
      fixture.detectChanges();
    });
    

    En esta implementación actualizada, se crea un espía para el método ngOnInit del componente, lo cual asegurará que se llame cuando se invoque el método fixture.detectChanges(). La implementación del espía llama al método ngOnInit original del componente, pero también establece la variable portalState con la instantánea del selector portalState del almacén.

    Con esta actualización, el método afterInit debería ser llamado como se espera.

Comments are closed.