微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

ngrx - 大理石测试和 withLatestFrom

如何解决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 举报,一经查实,本站将立刻删除。