【问题标题】:Mocking MatSnackBar in Angular 8 & Jasmine在 Angular 8 和 Jasmine 中模拟 MatSnackBar
【发布时间】:2020-02-14 04:43:49
【问题描述】:

我有一个使用 Angular Material MatSnackBar 的 Angular 8 应用程序,我正在尝试测试是否调用了该类的 open() 方法。对 open() 方法的调用在 NgRx 存储选择器的主体中,如下所示:

ngOnInit() {
  this.store.dispatch(fromStore.getFeaturedPlaylists());

  this.subscription = this.store.pipe(
    select(fromStore.selectError),
    filter(err => !!err),
    switchMap((err) => this.snackBar.open(
      `Error: ${err.message}`,
      'Try again',
      {duration: 5000}).afterDismissed())
  ).subscribe(() => this.store.dispatch(fromStore.getFeaturedPlaylists()));
}

我的测试的相关部分如下所示:

describe('FeaturedPlaylistsComponent', () => {

  let component: FeaturedPlaylistsComponent;
  let fixture: ComponentFixture<FeaturedPlaylistsComponent>;
  let matSnackBarSpy: jasmine.SpyObj<MatSnackBar>;

  beforeEach(async(() => {
    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<MatSnackBar>(MatSnackBar);
  }));

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

  describe('#ngOnInit()', () => { // fails
    // lots of other test...
    it('should call MatSnackBar.open() on error', () => {
      const error = new HttpErrorResponse({error: 'Some error'});

      component.ngOnInit();
      store.dispatch(fromStore.setError({error}));

      expect(matSnackBarSpy.open).toHaveBeenCalled();
    });
  });

});

现在我知道这个 ngOnInit() 函数正在工作,因为我有另一个测试来测试 getFeaturedPlayists() 操作被调度了两次:一次在函数的第一行,一次在 subscribe 块中:

it('should dispatch a getFeaturedPlaylists() action on error', () => { // 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})]
  ]);
});

老实说,我很惊讶这个测试有效:我会假设我需要一个 tick(5000) 来等待对话被解除,所以也许这里实际上发生了更险恶的事情。

另一件事:如果我将open() 调用移动到函数的第一行,如下所示:

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 => !!err),
  //   switchMap((err) => this.snackBar.open(
  //     `Error: ${err.message}`,
  //     'Try again',
  //     {duration: 5000}).afterDismissed())
  // ).subscribe(() => this.store.dispatch(fromStore.getFeaturedPlaylists()));
}

should call MatSnackBar.open() on error 测试有效,所以我的理解是这与在此商店选择器中调用 open() 有关。

谁能告诉我为什么should dispatch a getFeaturedPlaylists() action on error 测试有效而should call MatSnackBar.open() on error 测试无效?

【问题讨论】:

    标签: angular typescript unit-testing jasmine ngrx


    【解决方案1】:

    好的,我意识到我使用的是模拟商店,因此没有选择器实际工作。使用真实的商店进行这些测试,稍微摆弄一下,我就让它们工作了。

    【讨论】:

    • 您好,我也需要像您的代码一样进行测试。您能否给我测试一下您已经工作过并且完全适用于上述代码?我真的被困太久了,因为我是新来的角度测试..
    • 我收到错误Error: &lt;toHaveBeenCalled&gt; : Expected a spy, but got Function. 这行expect(matSnackBarSpy.open).toHaveBeenCalled(); ..
    猜你喜欢
    • 1970-01-01
    • 2020-03-21
    • 2015-05-04
    • 1970-01-01
    • 1970-01-01
    • 2016-03-16
    • 2021-09-20
    • 1970-01-01
    • 2022-11-02
    相关资源
    最近更新 更多