我正在尝试在 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()])
},
...
答案 0 :(得分:2)
所以,我的真正问题是如何在Repository
上模拟NestJS
。
由于某些原因,当我使用@golevelup/nestjs-testing
进行模拟时,会发生奇怪的事情!
我真的没有在@golevelup/nestjs-testing
上找到关于此的很好的文档,因此,我放弃了使用它。
我对这个问题的解决方案是仅使用Jest
和NestJS
函数...结果代码为:
服务:
// 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)
@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" });