Broma con NestJS y función asíncrona
Estoy intentando probar una función asíncrona de service
en nestJS .
esta función es asincrónica ... básicamente obtiene un valor (JSON) de la base de datos (usando el repositorio - TypeORM), y cuando obtiene los datos con éxito, "transforma" a una clase diferente (DTO) ... la implementación:
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;
});
}
usando un controlador, verifiqué que esto funcionaba bien. Ahora, estoy tratando de usar Jest para hacer las pruebas, pero sin éxito ... Mi problema es cómo burlarme de la findOne
función de repository
...
Editar : ¡Estoy tratando de usar @golevelup/nestjs-testing
para burlarme Repository
!
Ya me burlé del repository
, pero por alguna razón, el resolve
nunca se llama ..
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);
});
})
- las
expect(await repo.findOne()).toEqual(mockedConfig);
obras grandes; expect(await service.getAppConfig()).toEqual(expectedReturn);
obtuvo un tiempo de espera =>Async callback was not invoked within the 5000 ms timeout specified by jest.setTimeout
;
usando debug, veo que service.getAppConfig()
se llama, repository.findOne()
también, pero .then
nunca se llama al repositorio de findOne.
Actualización : estoy tratando de simular el repositorio usando @golevelup/nestjs-testing
y, por alguna razón, el resultado simulado no funciona en el servicio. Si me burlo del repositorio usando solo jest
(como el código a continuación), la prueba funciona ... entonces, creo que mi problema real es @golevelup/nestjs-testing
.
...
provide: getRepositoryToken(Config),
useValue: {
find: jest.fn().mockResolvedValue([new Config()])
},
...
Respuestas
Por lo tanto, mi verdadero problema es cómo me estoy burlando de la Repository
sobre NestJS
. Por alguna razón, cuando me burlo de usar el @golevelup/nestjs-testing
, ¡suceden cosas raras!
Realmente no encontré una buena documentación sobre esto @golevelup/nestjs-testing
, así que dejé de usarlo.
Mi solución para la pregunta fue usar solo Jest
y NestJS
funciones ... el código de resultado fue:
Servicio :
// 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;
})
}
Prueba :
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);
})
});
})
algunas fuentes utilizadas para esta solución: https://github.com/jmcdo29/testing-nestjs/tree/master/apps/typeorm-sample
Creo que expect(await repo.findOne()).toEqual(mockedConfig);
funciona porque te burlaste de él, así que vuelve de inmediato. En el caso de expect(await service.getAppConfig()).toEqual(expectedReturn);
, no se burló de él, por lo que probablemente esté tomando más tiempo, por lo que la it
función regresa antes de que se Promise
resuelva por completo.
Los comentarios que publicó de la documentación de broma deberían funcionar si se burla de la llamada a getAppConfig()
.
service.getAppConfig = jest.fn(() => Promise.resolve(someFakeValue))
o
spyOn(service, 'getAppConfig').and.mockReturnValue(Promise.resolve(fakeValue))