Bercanda dengan NestJS dan fungsi async
Saya mencoba menguji fungsi async dari sebuah service
di nestJS .
fungsi ini async ... pada dasarnya mendapatkan nilai (JSON) dari database (menggunakan repositori - TypeORM), dan ketika berhasil mendapatkan datanya, "transformasikan" ke kelas yang berbeda (DTO) ... implementasinya:
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;
});
}
menggunakan pengontrol, saya memeriksa bahwa ini berfungsi dengan baik. Sekarang, saya mencoba menggunakan Jest untuk melakukan tes, tetapi tidak berhasil ... Masalah saya adalah bagaimana meniru findOne
fungsi dari repository
..
Sunting : Saya mencoba menggunakan @golevelup/nestjs-testing
untuk mengejek Repository
!
Aku sudah mengejeknya repository
, tapi entah kenapa, resolve
tidak pernah dipanggil ..
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);
karya - karyanya bagus;expect(await service.getAppConfig()).toEqual(expectedReturn);
mendapat waktu tunggu =>Async callback was not invoked within the 5000 ms timeout specified by jest.setTimeout
;
menggunakan debug, saya melihat bahwa yang service.getAppConfig()
dipanggil, repository.findOne()
juga, tetapi .then
repositori findOne tidak pernah dipanggil.
Pembaruan : Saya mencoba mengejek repositori menggunakan @golevelup/nestjs-testing
, dan untuk beberapa alasan, hasil tiruan tidak berfungsi pada layanan. Jika saya mengejek repositori hanya dengan menggunakan jest
(seperti kode di bawah), tesnya bekerja ... jadi, saya pikir masalah saya sebenarnya itu @golevelup/nestjs-testing
.
...
provide: getRepositoryToken(Config),
useValue: {
find: jest.fn().mockResolvedValue([new Config()])
},
...
Jawaban
Jadi, masalah sebenarnya saya adalah bagaimana saya mengejek Repository
di NestJS
. Untuk beberapa alasan, ketika saya mengejek menggunakan @golevelup/nestjs-testing
, hal-hal aneh terjadi!
Saya benar-benar tidak menemukan dokumentasi yang bagus tentang ini @golevelup/nestjs-testing
, jadi, saya berhenti menggunakannya.
Solusi saya untuk pertanyaan itu adalah dengan hanya menggunakan Jest
dan NestJS
fungsi ... kode hasilnya adalah:
Layanan :
// 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;
})
}
Tes :
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);
})
});
})
beberapa sumber yang digunakan untuk solusi ini: https://github.com/jmcdo29/testing-nestjs/tree/master/apps/typeorm-sample
Saya pikir expect(await repo.findOne()).toEqual(mockedConfig);
berhasil karena Anda mengejeknya, jadi itu langsung kembali. Dalam kasus expect(await service.getAppConfig()).toEqual(expectedReturn);
, Anda tidak memalsukannya sehingga mungkin memerlukan lebih banyak waktu, sehingga it
fungsi tersebut kembali sebelum Promise
diselesaikan sepenuhnya.
Komentar yang Anda posting dari dokumentasi lelucon harus melakukan trik jika Anda mengejek panggilan tersebut getAppConfig()
.
service.getAppConfig = jest.fn(() => Promise.resolve(someFakeValue))
atau
spyOn(service, 'getAppConfig').and.mockReturnValue(Promise.resolve(fakeValue))