ngrx - 大理石测试和 withLatestFrom
ngrx - marble testing and 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
,而是 returns 已经存在的 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);
});
我正在使用 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
,而是 returns 已经存在的 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);
});