title: How to mock a @ViewChild MatTabGroup in jest?
body: <p>I'm trying to test a new piece of code I added to my project. It allows users to select a tab on a page and when they refresh, the page is loaded on the same tab. I'm using localstorage to do this. </p>
  
  <p>The issue I'm having is in the tests where it cannot set <code>selectedIndex</code> of <code>undefined</code>.</p>
  
  <p>In the html on the mat-tab I have an event handler (<code>selectedTabChange</code>):</p>
  
  <pre><code>&lt;mat-tab-group
    [selectedIndex]="selectedTab.value"
    (selectedIndexChange)="selectedTab.setValue($event)"
    (selectedTabChange)="handleMatTabChange($event)"
  &gt;
    &lt;mat-tab label="Tab 1"&gt;
      &lt;div *ngIf="selectedTab.value === 0"&gt; ... &lt;/div&gt;
    &lt;/mat-tab&gt;
  
    &lt;mat-tab label="Tab 2"&gt;
      &lt;div *ngIf="selectedTab.value === 1"&gt; ... &lt;/div&gt;
    &lt;/mat-tab&gt;
  
    &lt;mat-tab label="Tab 3"&gt;
      &lt;div *ngIf="selectedTab.value === 2"&gt; ... &lt;/div&gt;
    &lt;/mat-tab&gt;
  
  &lt;/mat-tab-group&gt;
  </code></pre>
  
  <p>In the component I have </p>
  
  <pre><code>@ViewChild(MatTabGroup) tabGroup: MatTabGroup;
  
  
  ngAfterViewInit() {
    const index = Number(localStorage.getItem('userTabLocation')) || 0;
    this.tabGroup.selectedIndex = index;
  }
  
  handleMatTabChange(event: MatTabChangeEvent) {
    localStorage.setItem('userTabLocation', String(event.index));
  }
  </code></pre>
  
  <p>Tests:</p>
  
  <p>Checking if ViewChild is defined but it's <code>undefined</code>.</p>
  
  <pre><code>it('Should have `ViewChild` variable defined', () =&gt; {
    expect(component.tabGroup).toBeDefined();
  });
  </code></pre>
  
  <p>Also in some of my other tests I get:</p>
  
  <pre><code>TypeError: Cannot set property 'selectedIndex' of undefined
  
     99 |   }
    100 | 
  &gt; 101 |   ngAfterViewInit() {
        |   ^
    102 |     const index = Number(localStorage.getItem('userTabLocation')) || 0;
    103 |     this.tabGroup.selectedIndex = index;
  </code></pre>
  
  <p>Things I have tried:</p>
  
  <ol>
  <li>I read this really helpful article <a href="https://blog.angularindepth.com/angular-unit-testing-viewchild-4525e0c7b756" rel="nofollow noreferrer">https://blog.angularindepth.com/angular-unit-testing-viewchild-4525e0c7b756</a></li>
  <li><p>Since my view child is a MatTabGroup, I've no idea how to stub that so the above article didn't help much. I tried this but that broke even more tests:</p>
  
  <pre><code>component.tabGroup = TestBed.createComponent(MatTabGroup).componentInstance as MatTabGroup;
  </code></pre></li>
  <li><p>I have added the MatTabGroup into the providers like so, which didn't help:</p>
  
  <pre><code>TestBed.configureTestingModule({
        imports: [ ... ],
        declarations: [ ... ],
        providers: [
        {
           provide: MatTabGroup,
        }],
  }).compileComponents();
  </code></pre></li>
  <li><p>I have added the useValues into the providers with the matTabGroup like so, which also didn't help:</p>
  
  <pre><code>TestBed.configureTestingModule({
        imports: [ ... ],
        declarations: [ ... ],
        providers: [
        {
           provide: MatTabGroup,
           useValues: {
              selectedIndex: 0,
           }
        }],
  }).compileComponents();
  </code></pre></li>
  <li><p>I have added the <code>MatTabsModule</code> into the imports, also no luck:</p>
  
  <pre><code>TestBed.configureTestingModule({
        imports: [ MatTabsModule ],
        declarations: [ ... ],
  }).compileComponents();
  </code></pre>
  
  <p>But that gives the following error:</p>
  
  <pre><code>Template parse errors:
  More than one component matched on this element.
  Make sure that only one component's selector can match a given element.
  Conflicting components: MatTab,MatTab ("
  </code></pre>
  
  <p>(EDIT): This was happening because I was importing <code>MaterialModule</code> too.</p></li>
  </ol>
  
  <p>Any ideas? Really stuck on this. </p>
  
  <p>Thank you in advance.</p>