提供基于运行时标志的API或模拟版本

问题描述 投票:3回答:2

我想基于运行时标志提供API接口的模拟或实际实现。这是我目前的做法:

providers:[{
  provide: MyApi,
  useFactory: () => {
     return env.useSpoofData ? mockMyApi : MyApi
  }
}]

我已将mockMyApi定义为:

export const mockMyApi: MyApi = {
  get(): Observable<MyResponse> {
    const resp: MyResponse = {items};
    return observableOf(resp);
  },
};

这个模拟版本有效,但真正的版本,当以这种方式提供时,不起作用。 (如果我不完全覆盖这个提供者那么真正的版本是有效的)

我已经尝试了两种方法来解决“真实”实现的符号。

一:

provide: MyApi,
deps: [MyApi],
useFactory: (real: MyApi) => env.spoof ? mockMyApi : real;

失败。构建时的循环依赖。

二:

provide: MyApi,
deps: [Injector],
useFactory: (inj: Injector) => env.spoof ? mockMyApi : inj.get(MyApi);

失败。堆栈在运行时溢出。

从useFactory返回时,实例化或提供类的正确方法是什么?或者,是否有更简单的方法来提供者覆盖?

angular typescript
2个回答
1
投票

您提供工厂,因此您不能简单地将注入令牌作为工厂结果传递。 mockMyApi是一个常数,而MyApi是一个类。因此,您需要创建该类的对象。这就是工厂通常使用的。使用deps传递依赖关系,例如HttpClient

providers:[{
  provide: MyApi,
  useFactory: (http: HttpClient) => {
     return env.useSpoofData ? mockMyApi : new MyApi(/* args, e.g. http */)
  },
  deps: [HttpClient]
}]

1
投票

我能找到的最佳解决方案是创建一个新的“包装”API。然后,将所有消费者更改为指向新的MyApiWrapped。在您的新实施中:

provide: MyApiWrapped,
deps: [Injector],
useFactory: (inj: Injector) => env.spoof ? mockMyApi : inj.get(MyApi);

这样,您可以提供任一实现,而不会导致循环依赖。此外,在这里使用Injector意味着您允许Angular管理服务的缓存单例实例并使用正确的依赖关系进行备份。

© www.soinside.com 2019 - 2024. All rights reserved.