ngrx/data может значительно облегчить жизнь проектам, использующим преимущества ngrx. Позволив библиотеке выполнять работу с шаблонным кодом, который обычно приходится писать самостоятельно, вы можете ускорить как адаптацию, так и время разработки.

Тем не менее, самым большим недостатком, с которым я столкнулся, является отсутствие полной документации и отсутствие документации по модульному тестированию. Это может немного усложнить жизнь, особенно если ваш сервер не идеален (если ваш сервер идеален, прекратите читать и немедленно угостите своих инженеров по серверу кофе!)

И, конечно же, если мы пишем код, мы хотим иметь возможность его протестировать. Допустим, у нас есть объект с именем Location и конечная точка API, которая будет принимать запрос PUT на /some/endpoint/${locationId}/addToGroup, который принимает полезную нагрузку, представляющую собой просто объект, похожий на { id: ${groupId} }, и добавляет этот Location в группу с идентификатором, который вы указали в полезной нагрузке.

Ваша служба сущности может иметь метод, который выглядит следующим образом:

export class LocationEntityService extends EntityCollectionServiceBase<Location> {
constructor(
private _locationDataService: LocationDataService,
serviceElementsFactory: EntityCollectionServiceElementsFactory
) {
  super('Location', serviceElementsFactory);
}
  addLocationToGroup(locationId: number, groupId: number) {
    return this._locationDataService.addLocationToGroup(locationId, groupId).pipe(
    map((result) => this.updateOneInCache(result),
    switchMap(() => this.entityMap$),
    switchMap((entityMap) => entityMap[locationId])
  }
}

Итак, вы написали метод, который принимает ваше местоположение и идентификаторы группы, передает их в службу данных, затем обновляет ваш магазин ответом от службы данных и возвращает обновленное местоположение любому компоненту, вызывающему этот метод.

Если вы настраиваете тесты, вы можете начать с чего-то вроде этого:

TestBed.configureTestingModule({
  providers: [
    LocationDataService,
    LocationEntityService
  ],
  imports: [
    HttpClientTestingModule,
  ]
});

Это не удается со следующей ошибкой:

NullInjectorError: StaticInjectorError(DynamicTestModule)[LocationDataService -> HttpUrlGenerator]:
      StaticInjectorError(Platform: core)[LocationDataService -> HttpUrlGenerator]:
        NullInjectorError: No provider for HttpUrlGenerator!

Это ссылка на HttpUrlGenerator в службе данных. Хорошо, давайте импортируем и предоставим HttpUrlGenerator и попробуем еще раз...

TypeError: httpUrlGenerator.entityResource is not a function

Что ж, давайте вернемся и смоделируем службу данных, чтобы наши провайдеры выглядели примерно так….

providers: [
  LocationEntityService,
  {
  provide: LocationDataService,
    useValue: {
      addLocationToGroup: () => of({}),
    },
  },
]

И когда мы попробуем снова:

NullInjectorError: StaticInjectorError(DynamicTestModule)[LocationEntityService -> EntityCollectionServiceElementsFactory]:
      StaticInjectorError(Platform: core)[LocationEntityService -> EntityCollectionServiceElementsFactory]:
        NullInjectorError: No provider for EntityCollectionServiceElementsFactory!

Мы видим, что это может быстро выйти из-под контроля, когда нужно будет предоставлять и имитировать все больше и больше только для нескольких простых модульных тестов.

Самое простое решение — создать хранилище только для этого набора модульных тестов!

Вы захотите предоставить свой EntityDataService и импортировать следующие модули: StoreModule, EffectsModule и EntityDataModule. В случае EntityDataModule вам нужно будет указать entityMetadata так же, как вы обычно это делаете при настройке сущности. В итоге это будет выглядеть так:

let entityMetaData = {
  Location: {}
};

и ваша тестовая установка будет выглядеть так:

TestBed.configureTestingModule({
  providers: [LocationDataService, LocationEntityService, EntityDataService],
  imports: [
    HttpClientTestingModule,
    StoreModule.forRoot({}),
    EffectsModule.forRoot([]),
    EntityDataModule.forRoot({
      entityMetadata: entityMetaData,
    }),
  ],
});

И вот вы «готовы»! С этого момента вы должны иметь возможность настраивать свои тесты, как обычно, внедряя и шпионя за вашими сервисами или имитируя их по мере необходимости и так далее.

Надеюсь, кто-то найдет это полезным! Моя команда на работе какое-то время боролась, и в итоге ей пришлось копаться в исходном коде ngrx/data, чтобы понять, как добиться успешного запуска тестов.