如何使用NgRx-Effects中的LatestFrom商店注入测试多个?

时间:2019-03-28 10:53:39

标签: angular typescript unit-testing testing ngrx

在我们的有角度的Web应用程序中,我们有一些NgRx效果,它们使用了来自商店不同部分的不同信息。为此,我们使用了推荐的withLatestFrom方法:

withLatestFrom(
   this.store.pipe(select(...)),
   this.store.pipe(select(...)),
   ...
)

虽然这种方法在生产中似乎可以很好地工作,但对效果进行单元测试却感到可怕。

对于我们的单元测试,我们当前使用的是茉莉花大理石,茉莉花间谍对象和ngrx MockStore(NgRx 7+)。困难的部分是提供必要的存储状态,以便选择器可以正常工作。

示例效果,但我们没有单元测试:

@Effect()
getStammdatenDetails$: Observable<Action> = this.actions$.pipe(
   ofType(StammdatenItemDetailActionTypes.REQUEST_DETAILS),
   withLatestFrom(
      this.store.pipe(select(fromRoot.getMetadata)),
      this.store.pipe(select(fromRoot.getCustomerId)),
      this.store.pipe(select(fromRoot.getRouterParams))
   ),
   mergeMap(([action, metadata, customerId, params]) => {
      *effect logic*
   })
);

也许有人可以提供更多的见解或指向我们所缺少的文档的有用链接?

如果有一种方便的方法可以对这些效果进行单元测试,或者如何将这些效果重构为更“可测试的”(无需将问题移至我们无法测试的另一段代码,我真的很感激)然后)。

1 个答案:

答案 0 :(得分:0)

我建议做这样的事情:

describe('ChapterEffects', () => {
  const actions$ = new Subject<any>();
  let effects: ChapterEffects;

  beforeEach(() => {
    TestBed.configureTestingModule({
      providers: [
        TestedEffects,
        provideMockActions(() => actions$),
        ...otherMocks,
      ],
    });

    effects = TestBed.get(ChapterEffects);
  });

  it('', () => {

  });
});

经过测试的效果:

  @Effect()
  fetchData$ = this.actions$.pipe(
    ofType<FetchAction>(ActionTypes.FetchAction),
    switchMap(({ payload }) => {
      return this.someService
        .get(payload)
        .pipe(
          map((data) => new LoadAction(data)),
          catchError(() => new ErrorAction()),
        );
    }),
  );

多数民众赞成在发挥作用和测试。您想测试FetchAction是否将调用get请求并在请求完成时加载LoadAction

第一件事是在testBet中模拟someService:

const otherMocks = [ { provide: SomeService, useValue: { get: () => of(42)} }, ]

现在在您的测试运行时中,this.someService将为{ get: () => of(42)} }

现在让我们模拟FetchAction。在测试中,actions$是主题,因此您可以调用actions$.next(new FetchRequest(7))(7是有效负载)。

然后,out效果应该以42发出LoadAction,

it('', (done) => {
  effect.fetchData$.subscribe(action => {
    expect(action.payload).toEqual(42);
  }
  done()
  actions$.next(7);
});