首页 > 解决方案 > 如何通过传入具有自定义值的 ConfigService 来测试 nestjs 服务?

问题描述

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

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();
  });
})

我愿意接受任何非 hacky 的建议,我只想标记我的应用程序!

标签: typescriptdependency-injectionnestjslaunchdarkly

解决方案


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

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();
  });
})

推荐阅读