Как сделать так, чтобы Angular mock-сервис работал в виде дерева - PullRequest
0 голосов
/ 06 марта 2020

Контекст

В проекте Angular 9 я работаю в двух средах: production & mock .

В ядре Модуль, я проверяю наличие фиктивной среды.

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

  • Если сборка производится с конфигурацией prod, внедряются реальные сервисы.

Я делаю это так:

core.module.ts

@NgModule({
  declarations: [],
  providers: [],
  imports: [BrowserModule, HttpClientModule],
  exports: [],
})
export class CoreModule {}

country.service.proxy.ts

const countryServiceFactory = (
  _http: HttpClient,
  _errorUtil: ErrorUtilService
) => {
  return isMock
    ? new ServiceMock()
    : new Service(_http, _errorUtil);
};

@Injectable({
  providedIn: CoreModule,
  useFactory: countryServiceFactory,
})
export abstract class CountryServiceProxy {
  abstract getCountries(): Observable<CountryWithLanguages[]>;
}

Где ServiceMock и Service реализуют один и тот же интерфейс.

Это работает.

Задача

Код не Дерево качается . В результате в мой пакет (когда я запускаю ng build --prod) включены даже фиктивные сервисы.

Я хочу переключать каждый сервис с макета на продукт во время разработки.

Цель

Как я могу сделать Angular для объединения только той услуги, которую планируется использовать?


Я использую:

Angular CLI: 9.0.4
Node: 13.6.0
OS: darwin x64

Ivy Workspace: Yes

Спасибо! :)

1 Ответ

1 голос
/ 06 марта 2020

Я только что попробовал один подход, который, кажется, работает:

  • Объявите соответствующую фабрику обслуживания в ваших environment.{env}.ts файлах
  • Используйте фабрику среды в качестве поставщика услуг

Моя тестовая установка:

базовый класс

@Injectable()
export abstract class TestService {
  abstract environment: string;
}

служба разработки

@Injectable()
export class DevTestService extends TestService {
  environment = 'qwertydev';
}

сервисное обслуживание

@Injectable()
export class ProdTestService extends TestService {
  environment = 'qwertyprod';
}

environment.ts

export const environment = {
  testServiceFactory: () => new DevTestService()
};

environment.production.ts

export const environment = {
  testServiceFactory: () => new ProdTestService()
};

app.module.ts

providers: [
  { provide: TestService, useFactory: environment.testServiceFactory }
],

app.component.ts

constructor(private testService: TestService) {}

ngOnInit() {
  console.log(this.testService.get());
}

Когда я проверяю свой файлы сборки, я нахожу только qwertydev в сборке dev и qwertprod в сборке prod, что говорит о том, что они были потрясены деревом.

Я использовал строки qwerty*, чтобы упростить его. поиск файлов сборки после минимизации.

Объявление сервисов в модуле

Я объявил провайдера в модуле, чтобы избежать циклических ссылок. Циркулярную ссылку легко ввести, объявив службу как providedIn: Module.

Вы можете обойти эту проблему, объявив сторонний модуль, но это кажется излишним.

Я продемонстрировал это в более старом ответе: @ Injectable () массив декоратора и провайдеров

Альтернативные подходы

Это не вполне чувствовать себя правильно, объявляя фабрики обслуживания в файлах среды Я сделал это для тестирования просто для простоты. Вы можете создать свой собственный набор c файлов, специфичных для среды, которые перезаписываются во время сборки так же, как файлы среды, но, откровенно говоря, это звучит как кошмар обслуживания.

...