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