Как протестировать несколько с последними инъекциями из магазина в NgRx-эффектах? - PullRequest
1 голос
/ 28 марта 2019

В нашем угловом веб-приложении есть несколько NgRx-эффектов, которые используют различную информацию из разных частей нашего магазина. Для этого мы используем рекомендуемый withLatestFrom -приступ:

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

В то время как этот подход, кажется, работает нормально в производстве, он чувствует себя ужасно для модульного тестирования эффектов.

Для наших юнит-тестов в настоящее время мы используем жасминовые шарики, жасминовые шпионские объекты и MockStore ngrx (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 голосов
/ 29 марта 2019

Предлагаю сделать что-то вроде этого:

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 вызывать запрос на получение и загрузить LoadAction, когда запрос будет завершен.

Первое, что нужно сделать, это некая служба в testBet:

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

теперь во время выполнения теста this.someService будет { get: () => of(42)} }.

Теперь давайте посмеемся над FetchAction. В тесте actions$ это субъект, поэтому вы можете позвонить actions$.next(new FetchRequest(7)) (7 - полезная нагрузка).

Тогда эффект out должен испускать LoadAction с 42, поэтому:

it('', (done) => {
  effect.fetchData$.subscribe(action => {
    expect(action.payload).toEqual(42);
  }
  done()
  actions$.next(7);
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...