用NestJS和异步功能开玩笑

时间:2020-08-18 12:32:29

标签: nestjs typeorm ts-jest

我正在尝试在 nestJS 中测试service的异步功能。

此函数是异步的...基本上是从数据库(使用存储库-TypeORM)获取值(JSON),并且在成功获取数据后,“转换”为另一个类(DTO)... 实现:

async getAppConfig(): Promise<ConfigAppDto> {
  return this.configRepository.findOne({
    key: Equal("APPLICATION"),
  }).then(config => {
    if (config == null) {
      return new class implements ConfigAppDto {
        clientId = '';
        clientSecret = '';
      };
    }
    return JSON.parse(config.value) as ConfigAppDto;
  });
}

使用控制器,我检查是否可以正常工作。 现在,我正在尝试使用Jest进行测试,但没有成功... 我的问题是如何从findOne模拟repository函数。

编辑:我正在尝试使用@golevelup/nestjs-testing来模拟Repository

我已经嘲笑了repository,但是由于某种原因,从未调用过resolve

describe('getAppConfig', () => {
  const repo = createMock<Repository<Config>>();

  beforeEach(async () => {
    await Test.createTestingModule({
      providers: [
        ConfigService,
        {
          provide: getRepositoryToken(Config),
          useValue: repo,
        }
      ],
    }).compile();
  });

  it('should return ConfigApp parameters', async () => {
    const mockedConfig = new Config('APPLICATION', '{"clientId": "foo","clientSecret": "bar"}');
    repo.findOne.mockResolvedValue(mockedConfig);
    expect(await repo.findOne()).toEqual(mockedConfig); // ok

    const expectedReturn = new class implements ConfigAppDto {
      clientId = 'foo';
      clientSecret = 'bar';
    };
    expect(await service.getAppConfig()).toEqual(expectedReturn);

    // jest documentation about async -> https://jestjs.io/docs/en/asynchronous
    // return expect(service.getAppConfig()).resolves.toBe(expectedReturn);
  });
})
  • expect(await repo.findOne()).toEqual(mockedConfig);很好用
  • expect(await service.getAppConfig()).toEqual(expectedReturn);超时=> Async callback was not invoked within the 5000 ms timeout specified by jest.setTimeout;

使用调试,我看到service.getAppConfig()也被调用了repository.findOne(),但是findOne仓库的.then从未被调用。

更新:我正在尝试使用@golevelup/nestjs-testing模拟存储库,由于某种原因,模拟结果在服务中不起作用。 如果我仅使用jest(如下面的代码)模拟存储库,则该测试有效...因此,我认为我的真正问题是@golevelup/nestjs-testing

...
provide: getRepositoryToken(Config),
useValue: {
  find: jest.fn().mockResolvedValue([new Config()])
},
...

3 个答案:

答案 0 :(得分:2)

所以,我的真正问题是如何在Repository上模拟NestJS。 由于某些原因,当我使用@golevelup/nestjs-testing进行模拟时,会发生奇怪的事情!

我真的没有在@golevelup/nestjs-testing上找到关于此的很好的文档,因此,我放弃了使用它。

我对这个问题的解决方案是仅使用JestNestJS函数...结果代码为:

服务

// i'm injecting Connection because I need for some transactions later;
constructor(@InjectRepository(Config) private readonly configRepo: Repository<Config>, private connection: Connection) {}

async getAppConfig(): Promise<ConfigApp> {
  return this.configRepo.findOne({
    key: Equal("APPLICATION"),
  }).then(config => {
    if (config == null) {
      return new ConfigApp();
    }
    return JSON.parse(config.value) as ConfigApp;
  })
}

测试

describe('getAppConfig', () => {
  const configApi = new Config();
  configApi.key = 'APPLICATION';
  configApi.value = '{"clientId": "foo", "clientSecret": "bar"}';

  beforeEach(async () => {
    const module = await Test.createTestingModule({
      providers: [
        ConfigAppService,
        {
          provide: getRepositoryToken(Config),
          useValue: {
            findOne: jest.fn().mockResolvedValue(new
            Config("APPLICATION", '{"clientId": "foo", "clientSecret": "bar"}')),
          },
        },
        {
          provide: getConnectionToken(),
          useValue: {},
        }
      ],
    }).compile();

    service = module.get<ConfigAppService>(ConfigAppService);
  });

  it('should return ConfigApp parameters', async () => {
    const expectedValue: ConfigApp = new ConfigApp("foo", "bar");

    return service.getAppConfig().then(value => {
      expect(value).toEqual(expectedValue);
    })
  });
})

一些用于此解决方案的资源: https://github.com/jmcdo29/testing-nestjs/tree/master/apps/typeorm-sample

答案 1 :(得分:1)

我认为expect(await repo.findOne()).toEqual(mockedConfig);之所以有效是因为您对其进行了嘲笑,因此它立即返回。 对于expect(await service.getAppConfig()).toEqual(expectedReturn);,您没有对其进行模拟,因此可能要花费更多时间,因此it函数在Promise完全解决之前返回。

如果嘲笑对getAppConfig()的调用,那么从笑话文档中发布的评论应该可以解决问题。

service.getAppConfig = jest.fn(() => Promise.resolve(someFakeValue))

spyOn(service, 'getAppConfig').and.mockReturnValue(Promise.resolve(fakeValue))

答案 2 :(得分:0)

来自 This answer

@roberto-correia 让我怀疑我们使用 System.out.println(false && (true ^ true)); // false && false -> false System.out.println((false && true) || true); // false || true -> true 包中的 createMock 的方式是否有问题。

事实证明,该方法超过执行时间的原因与 @golevelup/nestjs-testing 没有实现模拟并且不返回任何内容有关,除非被告知这样做。

为了使方法起作用,我们必须让模拟方法在测试开始时解决一些问题:

createMock

一个基本的工作解决方案:

usersRepository.findOneOrFail.mockResolvedValue({ userId: 1, email: "some-random-email@email.com" });