Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Dependency injection NestJS-关于服务模拟的问题_Dependency Injection_Mocking_Nestjs - Fatal编程技术网

Dependency injection NestJS-关于服务模拟的问题

Dependency injection NestJS-关于服务模拟的问题,dependency-injection,mocking,nestjs,Dependency Injection,Mocking,Nestjs,我目前正在用NestJS重写我们的普通节点API服务器,我遇到了以下问题:我有一个CacheService,它充当redis的包装器,并被注入到各种其他服务中 现在,如果客户端请求包含一个自定义头(键:x-mock-redis,值:someRedisMockKey),并且如果服务器在调试模式下运行,而不是调用redis,则应返回模拟的json值(该值从名为someRedisMockKey的文件中读取) 我可以将我的CacheService的作用域设置为“Request”,并注入客户机请求,允许我

我目前正在用NestJS重写我们的普通节点API服务器,我遇到了以下问题:我有一个
CacheService
,它充当redis的包装器,并被注入到各种其他服务中

现在,如果客户端请求包含一个自定义头(键:
x-mock-redis
,值:
someRedisMockKey
),并且如果服务器在调试模式下运行,而不是调用redis,则应返回模拟的json值(该值从名为
someRedisMockKey
的文件中读取)

我可以将我的
CacheService
的作用域设置为“Request”,并注入客户机请求,允许我检查mocking头是否存在,如果在调试模式下运行,则返回mocked值。 但我发现这是违反直觉的,因为我的逻辑违反了单一责任原则,不应该在生产模式下运行。另外,我希望我的
CacheService
具有默认范围,而不是“请求”


如何更优雅地完成这项工作,有什么建议吗?

事先,如果我误解了问题或限制,请原谅,我会尝试解释它们,并指出应该是什么样子,我想

  • 生产总是使用Redis
  • 您可以在不同的端口上设置应用程序实例,使其与“暂存”(或其他)应用程序实例完全分离
如果可以满足第二个条件,则可以使用自定义模块并为服务应用不同的客户端包装(策略):

缓存模块的自定义提供程序

import * as redis from 'redis'
import { INTERNAL_CACHE_CLIENT, INTERNAL_CACHE_MODULE } from './cache.constants'
import { CacheModuleAsyncOptions, InternalCacheOptions } from './cache.module'
import CacheClientRedis from './client/cache-client-redis'
// ...

export const createAsyncClientOptions = (options: CacheModuleAsyncOptions) => ({
  provide: INTERNAL_CACHE_MODULE,
  useFactory: options.useFactory,
  inject: options.inject,
})

export const createClient = () => ({
  provide: INTERNAL_CACHE_CLIENT,
  useFactory: (options: InternalCacheOptions) => {
    const { production, debug, noCache, ...redisConfig } = options
    // pardon for the ifs ; )
    if (noCache) {
      return new CacheClientInMemory()
    }
    if (production) {
      return new CacheClientRedis(redis.createClient(redisConfig))
    }

    if (debug) {
      return new MockedCache()
    }    

    return new CacheClientMemory()
  },
  inject: [INTERNAL_CACHE_MODULE],
})
正如所注意到的,您可以在CacheClient周围使用任何包装器,在您的情况下,这些包装器将为文件中的数据提供服务。为简单起见,由任何缓存客户端实现的接口示例可以是:

export interface CacheClient {
  set: (key: string, payload: string) => Promise<boolean>
  get: (key: string) => Promise<string | null>
  del: (key: string) => Promise<boolean>
}
请随时指出它是否仍然违反原则,或者您确实需要在运行时做出决定


干杯

谢谢你有趣的输入。问题是我真的需要决定在运行时使用什么(例如,正如我试图描述的,当客户端发送特定的头时)。有什么想法吗?将把责任转移到CacheClient上,但这与服务本身非常相似,不过在这种情况下,客户端实现将作为一种策略:耸耸肩:
constructor(
    @Inject(INTERNAL_CACHE_CLIENT) private readonly cacheClient: CacheClient) {
  }