我正在使用 NGRX,并使用 Effects 发送 HTTP 请求。如果用户发送另一个请求,则应取消任何先前的请求。当我手动测试时它工作正常,但我希望能够对此进行单元测试。为了测试这一点,我模拟了发送 HTTP 请求并在一定延迟后发送响应的服务。然后,我有一个触发 4 个请求的 Marble hot observable。我希望我的效果只触发一次。但是,它根本没有被触发。
单元测试:
it('should only do one request at a time', fakeAsync(() => {
// Arrange
const data = createTestData();
const dataServiceSpy = TestBed.get(DataService);
dataServiceSpy.getData = jest.fn(
(query: DataQuery) => {
const waitTime = 1000 * + query.index;
return of(assets).pipe(delay(waitTime));
}
);
// Act
actions = hot('-abcd-|', {
a: new SearchData({ index: '6' }),
b: new SearchData({ index: '5' }),
c: new SearchData({ index: '4' }),
d: new SearchData({ index: '1' })
});
tick(10000);
// Assert
expect(effects.loadData$).toBeObservable(
hot('-a-|', { a: new SearchDataComplete(assets) })
);
}));
所以,我发送了 4 个搜索请求;第一个应该在 6 秒后返回数据,第二个应该在 5 秒后返回数据,依此类推。但是,我的单元测试失败了 loadData$ 是一个空的可观察对象,而它期望有一个项目。
如果我删除间谍中的延迟,它会按预期工作,并且 loadData$ 包含 4 个结果。
我的效果是使用 NX DataPersistence,如果您提供 id 函数,它会负责取消;如果新的操作带有相同的 id,它将取消初始请求。类似于使用 this.actions$.pipe(switchMap(...))
@Effect()
loadData$ = this.dataPersistence.fetch(ActionTypes.SearchData, {
id: (action, state) => {
return action.type
},
run: (action, state) => {
return this.dataService
.searchData(action.payload)
.pipe(
map(data => new SearchDataComplete(data))
);
},