【发布时间】: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