在我们的有角度的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*
})
);
也许有人可以提供更多的见解或指向我们所缺少的文档的有用链接?
如果有一种方便的方法可以对这些效果进行单元测试,或者如何将这些效果重构为更“可测试的”(无需将问题移至我们无法测试的另一段代码,我真的很感激)然后)。
答案 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);
});