Jack M
Jack M

Reputation: 2574

component unit testing services call resolved in the afterviewinit

I have a component that implement afterviewinit and in the ngAfterViewInit I have some service calls and a call to check the actives tabs but I am struggling to setup my unit test:

export class SomeComponent implements OnInit, AfterViewInit{
@ViewChild('tabGroup') tabGroup: MatTabGroup;

 ngOnInit(): void {}
 ngAfterViewInit(): void {
 const label = this.tabGroup._tabs.find((x: MatTab) => x.isActive).textLabel;
 
 //Service Call that use the label
 }
}

and in my test:

 describe('SomeComponent', () => {
        let component: SomeComponent;
        let fixture: ComponentFixture<SomeComponent>;
        
        
        beforeEach(waitForAsync(()=>{
        
        TestBed.configureTestingModule( declarations: [
                    SomeComponent,]
                    imports:[ MatTabsModule,]).compileComponents();
    });
                    
                                 
beforeEach(() => {
    fixture = TestBed.createComponent(someComponent);
    component = fixture.componentInstance;
    Object.defineProperty(component, 'tabs', { value: [], isActive: true});
    fixture.detectChanges();
  });

        it('should be created', () => {
            expect(component).toBeTruthy();
        });});

the test run ok but I am getting this error : AfterAll TypeError: Cannot read property 'textLabel' of undefined

I have tried using the:

afterEach(() => {
  fixture.destroy();
});

It seems to have resolved the first test but I am just wondering if there is a better way to do it. PS: Basically my question is how should I mock objects that are set in the ngAfterViewInit, for instance the tabs are viewchild Regards

Upvotes: 1

Views: 867

Answers (1)

satanTime
satanTime

Reputation: 13574

Because MatTabGroup is a dependency, I would suggest to mock it in the test. In order to do so a testing library such as ng-mocks can be used.

a sandbox with the solution: https://codesandbox.io/s/cool-chebyshev-wp7mr?file=/src/test.spec.ts

describe('SomeComponent', () => {
  // keep SomeComponent and mocks MatTabsModule
  beforeEach(() => MockBuilder(SomeComponent).mock(MatTabsModule));

  it('should be created', () => {
    // now we say that MatTabGroup._tabs should be a fake value
    MockInstance(MatTabGroup, '_tabs', new QueryList<MatTab>()).reset([
      // the value has 1 element
      // it is a fake MatTab with the desired value.
      MockService(MatTab, {
        isActive: true,
      }),
    ]);
    const component = MockRender(SomeComponent).point.componentInstance;

    expect(component).toBeTruthy();
  });
});

Upvotes: 1

Related Questions