Jest avec NestJS et fonction asynchrone
J'essaye de tester une fonction asynchrone d'un service
dans nestJS .
cette fonction est asynchrone ... en gros, obtenir une valeur (JSON) de la base de données (en utilisant le référentiel - TypeORM), et quand obtenir les données avec succès, "transformer" en une classe différente (DTO) ... l'implémentation:
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;
});
}
en utilisant un contrôleur, j'ai vérifié que cela fonctionnait bien. Maintenant, j'essaie d'utiliser Jest pour faire les tests, mais sans succès ... Mon problème est de savoir comment se moquer de la findOne
fonction repository
...
Edit : j'essaye de me @golevelup/nestjs-testing
moquer Repository
!
Je me suis déjà moqué du repository
, mais pour une raison quelconque, le resolve
n'est jamais appelé ..
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);
});
})
- les
expect(await repo.findOne()).toEqual(mockedConfig);
œuvres très bien; expect(await service.getAppConfig()).toEqual(expectedReturn);
obtenu un délai =>Async callback was not invoked within the 5000 ms timeout specified by jest.setTimeout
;
en utilisant le débogage, je vois que le service.getAppConfig()
est appelé, le repository.findOne()
aussi, mais le .then
référentiel of de findOne n'est jamais appelé.
Mise à jour : j'essaie de me moquer du référentiel en utilisant @golevelup/nestjs-testing
, et pour une raison quelconque, le résultat simulé ne fonctionne pas sur le service. Si je me moque du référentiel en utilisant uniquement jest
(comme le code ci-dessous), le test fonctionne ... donc, je pense que mon vrai problème est @golevelup/nestjs-testing
.
...
provide: getRepositoryToken(Config),
useValue: {
find: jest.fn().mockResolvedValue([new Config()])
},
...
Réponses
Donc, mon problème est de savoir comment je suis moqueur le Repository
sur NestJS
. Pour une raison quelconque, lorsque je me moque de l'utilisation de @golevelup/nestjs-testing
, des choses étranges se produisent!
Je n'ai vraiment pas trouvé de bonne documentation à ce sujet @golevelup/nestjs-testing
, alors j'ai renoncé à l'utiliser.
Ma solution pour la question était d'utiliser uniquement Jest
et des NestJS
fonctions ... le code de résultat était:
Service :
// 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;
})
}
Test :
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);
})
});
})
quelques sources utilisées pour cette solution: https://github.com/jmcdo29/testing-nestjs/tree/master/apps/typeorm-sample
Je pense expect(await repo.findOne()).toEqual(mockedConfig);
que ça marche parce que tu t'es moqué de ça, donc ça revient tout de suite. Dans le cas de expect(await service.getAppConfig()).toEqual(expectedReturn);
, vous ne vous en êtes pas moqués, donc cela prend probablement plus de temps, donc la it
fonction retourne avant la Promise
résolution complète.
Les commentaires que vous avez publiés à partir de la documentation de plaisanterie devraient faire l'affaire si vous vous moquez de l'appel à getAppConfig()
.
service.getAppConfig = jest.fn(() => Promise.resolve(someFakeValue))
ou
spyOn(service, 'getAppConfig').and.mockReturnValue(Promise.resolve(fakeValue))