如何解决ngrx - 大理石测试和 withLatestFrom
我正在使用 Angular 8 和 ngrx 8。我正在尝试为使用 withLatestFrom
从状态获取一些值的效果编写单元测试。为此,我正在使用 rxjs/testing/TestScheduler
。在那里,我有一个像这样的大理石图:
actions$ = hot('aa',{ a: actions.fetchUser({ id: 1 }));
和我的效果类似:
fetchUser$ = createEffect(() => this.actions$.pipe(
ofType(actions.fetchUser),withLatestFrom(this.store.select(selectors.user)),mergeMap(([{ id },user]) => {
console.log(user);
if (user.id === id) {
return of(user);
}
return this.userService.getUser(id).pipe(
map((user) => actions.updateUser({ user })),catchError(() => of(actions.updateUser({})))
)
})
))
这个想法是通过调用 userService
并更新状态来遍历第一个大理石框架;然后第二帧发生并且它看到在第一帧期间设置的 user.id
,因此它不会调用 userService
,而是返回已经处于该状态的 user
实例。 (这只是一个例子;最终目标是避免服务中的重复 HTTP 调用或如果用户 id 更改则取消前一个调用)。
问题是在弹珠图期间状态似乎没有更新,并且从 withLatestFrom
返回的用户对象始终是测试中设置的初始状态的对象。
我是 Angular 和 ngrx 测试的新手,所以我不确定这是预期的行为还是我做错了什么。
如果有人能推荐一种更好的方法来处理和测试这种情况,那也太棒了。
解决方法
我在模拟商店的 documentation 中看到了这个注释,上面写着“所有分派的动作都不会影响状态”,所以我猜在弹珠图期间状态不会改变。
我改变了我的测试,所以它在进入弹珠之前为用户设置了状态。现在是这样的:
it('should use the user in store when called with the same id',() => {
scheduler.run(({ hot,expectObservable }) => {
const fetchUser = actions.fetchUser({ id: 1 });
const updateUser = actions.updateUser({ user });
store.setState({
user
});
spyOn(userService,'getUser').and.callThrough();
actions$ = hot(
`a`,{ a: fetchUser }
);
// The result should come immediately because the user with the given id is already in the store
const expectedMarble = `a`;
const expectedValues = { a: updateUser };
expectObservable(effects.fetchUser$).toBe(expectedMarble,expectedValues);
});
expect(userService.getUser).not.toHaveBeenCalledWith(1);
});
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。