title: Mocking MatSnackBar in Angular 8 & Jasmine
body: <p>I have an Angular 8 application that uses the Angular Material <code>MatSnackBar</code> and I am trying to test that the <code>open()</code> method of the class is called. The call to the <code>open()</code> method is within the body of an NgRx store selector, like this:</p>
  
  <pre class="lang-js prettyprint-override"><code>ngOnInit() {
    this.store.dispatch(fromStore.getFeaturedPlaylists());
  
    this.subscription = this.store.pipe(
      select(fromStore.selectError),
      filter(err =&gt; !!err),
      switchMap((err) =&gt; this.snackBar.open(
        `Error: ${err.message}`,
        'Try again',
        {duration: 5000}).afterDismissed())
    ).subscribe(() =&gt; this.store.dispatch(fromStore.getFeaturedPlaylists()));
  }
  </code></pre>
  
  <p>The relevant part of my test looks like this:</p>
  
  <pre><code>describe('FeaturedPlaylistsComponent', () =&gt; {
  
    let component: FeaturedPlaylistsComponent;
    let fixture: ComponentFixture&lt;FeaturedPlaylistsComponent&gt;;
    let matSnackBarSpy: jasmine.SpyObj&lt;MatSnackBar&gt;;
  
    beforeEach(async(() =&gt; {
      const spy = jasmine.createSpyObj('MatSnackBar', ['open']);
  
      TestBed.configureTestingModule({
        declarations: [
          // other declarations here
          FeaturedPlaylistsComponent
        ],
        providers: [
          // other providers here
          {provide: MatSnackBar, useValue: spy}
        ]
      })
      .compileComponents();
  
      matSnackBarSpy = TestBed.get&lt;MatSnackBar&gt;(MatSnackBar);
    }));
  
    beforeEach(() =&gt; {
      fixture = TestBed.createComponent(FeaturedPlaylistsComponent);
      component = fixture.componentInstance;
      fixture.detectChanges();
    });
  
    describe('#ngOnInit()', () =&gt; { // fails
      // lots of other test...
      it('should call MatSnackBar.open() on error', () =&gt; {
        const error = new HttpErrorResponse({error: 'Some error'});
  
        component.ngOnInit();
        store.dispatch(fromStore.setError({error}));
  
        expect(matSnackBarSpy.open).toHaveBeenCalled();
      });
    });
  
  });
  </code></pre>
  
  <p>Now I know that this <code>ngOnInit()</code> function is working because I have another test that tests that the <code>getFeaturedPlayists()</code> action is dispatched twice: once on the first line of the function and once in the <code>subscribe</code> block:</p>
  
  <pre><code>it('should dispatch a getFeaturedPlaylists() action on error', () =&gt; { // succeeds
    const spy = spyOn(store, 'dispatch').and.callThrough();
    const error = new HttpErrorResponse({error: 'Some error'});
  
    component.ngOnInit();
    store.dispatch(fromStore.setError({error}));
  
    expect(spy).toHaveBeenCalledTimes(2);
    expect(spy.calls.allArgs()).toEqual([
      [fromStore.getFeaturedPlaylists()],
      [fromStore.setError({error})]
    ]);
  });
  </code></pre>
  
  <p>To be honest I'm surprised that this test works: I would have assumed that I would need a <code>tick(5000)</code> to wait for the dialog to be dismissed, so perhaps there is actually something more sinister going on here.</p>
  
  <p>Another thing: if I move the <code>open()</code> call to the first line of the function, like this:</p>
  
  <pre class="lang-js prettyprint-override"><code>ngOnInit() {
    this.snackBar.open(
      `Error: Some error`,
      'Try again',
      {duration: 5000});
    // this.store.dispatch(fromStore.getFeaturedPlaylists());
  
    // this.subscription = this.store.pipe(
    //   select(fromStore.selectError),
    //   filter(err =&gt; !!err),
    //   switchMap((err) =&gt; this.snackBar.open(
    //     `Error: ${err.message}`,
    //     'Try again',
    //     {duration: 5000}).afterDismissed())
    // ).subscribe(() =&gt; this.store.dispatch(fromStore.getFeaturedPlaylists()));
  }
  </code></pre>
  
  <p>the <code>should call MatSnackBar.open() on error</code> test works, so my understanding is that it is something to do with the call to <code>open()</code> being within this store selector.</p>
  
  <p>Can anyone tell me why the <code>should dispatch a getFeaturedPlaylists() action on error</code> test works and the <code>should call MatSnackBar.open() on error</code> test doesn't?</p>