如何通过传入具有自定义值的 ConfigService 来测试 nestjs 服务?

Posted

技术标签:

【中文标题】如何通过传入具有自定义值的 ConfigService 来测试 nestjs 服务?【英文标题】:How to test a nestjs service by passing in a ConfigService with custom values? 【发布时间】:2021-04-14 15:10:06 【问题描述】:

我创建了一个服务,它的模块如下所示:

launchdarkly.module.ts

@Module(
  providers: [LaunchdarklyService],
  exports: [LaunchdarklyService],
  imports: [ConfigService],
)
export class LaunchdarklyModule 

(此服务/模块是让应用程序使用 LaunchDarkly 功能标记)

如果您愿意,我很乐意展示服务实现,但为了缩短这个问题,我跳过了它。重要的一点是该服务导入了ConfigService(它用于获取 LaunchDarkly SDK 密钥)。

但是如何测试Launchdarkly 服务呢?它从ConfigService 读取一个密钥,所以我想编写测试,其中ConfigService 具有各种值,但经过数小时的尝试,我无法弄清楚如何在测试中配置ConfigService

这是测试:

launchdarkly.service.spec.ts

describe('LaunchdarklyService', () => 
  let service: LaunchdarklyService;

  beforeEach(async () => 
    const module: TestingModule = await Test.createTestingModule(
      providers: [LaunchdarklyService],
      imports: [ConfigModule],
    ).compile();

    service = module.get<LaunchdarklyService>(LaunchdarklyService);
  );

  it("should not create a client if there's no key", async () => 
    // somehow I need ConfigService to have key FOO=undefined for this test
    expect(service.client).toBeUndefined();
  );

  it("should create a client if an SDK key is specified", async () => 
    // For this test ConfigService needs to specify FOO=123
    expect(service.client).toBeDefined();
  );
)

我愿意接受任何非骇人听闻的建议,我只想对我的应用程序进行功能标记!

【问题讨论】:

【参考方案1】:

假设LaunchdarklyService 需要ConfigService 并且注入到构造函数中,您可以通过使用Custom Provider 提供ConfigService 的模拟变体,以返回您需要的自定义凭据。例如,您的测试模拟可能看起来像

describe('LaunchdarklyService', () => 
  let service: LaunchdarklyService;
  let config: ConfigService;

  beforeEach(async () => 
    const module: TestingModule = await Test.createTestingModule(
      providers: [LaunchdarklyService, 
        provide: ConfigService,
        useValue: 
          get: jest.fn((key: string) => 
            // this is being super extra, in the case that you need multiple keys with the `get` method
            if (key === 'FOO') 
              return 123;
            
            return null;
          )
        
      ],
    ).compile();

    service = module.get<LaunchdarklyService>(LaunchdarklyService);
    config = module.get<ConfigService>(ConfigService);
  );

  it("should not create a client if there's no key", async () => 
    // somehow I need ConfigService to have key FOO=undefined for this test
    // we can use jest spies to change the return value of a method
    jest.spyOn(config, 'get').mockReturnedValueOnce(undefined);
    expect(service.client).toBeUndefined();
  );

  it("should create a client if an SDK key is specified", async () => 
    // For this test ConfigService needs to specify FOO=123
    // the pre-configured mock takes care of this case
    expect(service.client).toBeDefined();
  );
)

【讨论】:

谢谢! jest.spyOn(config, 'get').mockReturnValueOnce 产生 Error: Cannot spyOn on a primitive value; undefined given,但核心 useValue:get: ... 模式有效。 哎呀,忘了在beforeEach 中添加一行。我会对此进行编辑

以上是关于如何通过传入具有自定义值的 ConfigService 来测试 nestjs 服务?的主要内容,如果未能解决你的问题,请参考以下文章

具有自定义值的 Paypal 结帐表单[关闭]

js Array 创建具有自定义初始值的数组

Wordpress 自定义 SQL 以获取三个具有给定元值的帖子

如何通过传入枚举值和属性类型来获取枚举的自定义属性?

如何通过自定义装饰器记录@Input@Output值的值。

html 具有动态值的自定义侧滑块