Jest กับ NestJS และฟังก์ชัน async
ฉันพยายามที่จะมีการทดสอบฟังก์ชั่น async ของservice
ในnestJS
ฟังก์ชันนี้เป็น async ... โดยทั่วไปจะได้รับค่า (JSON) จากฐานข้อมูล (โดยใช้ที่เก็บ - TypeORM) และเมื่อรับข้อมูลสำเร็จ "แปลง" เป็นคลาสอื่น (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()
เช่นกัน แต่.then
พื้นที่เก็บข้อมูลของ findOne ไม่เคยถูกเรียก
อัปเดต : ฉันกำลังพยายามจำลองที่เก็บโดยใช้@golevelup/nestjs-testing
และด้วยเหตุผลบางประการผลลัพธ์ที่เยาะเย้ยไม่สามารถใช้งานได้ในบริการ ถ้าฉันเยาะเย้ยพื้นที่เก็บข้อมูลโดยใช้เพียงjest
(เช่นรหัสด้านล่าง) ผลงานการทดสอบ ... @golevelup/nestjs-testing
ดังนั้นผมคิดว่าปัญหาที่แท้จริงของฉันมันเป็น
...
provide: getRepositoryToken(Config),
useValue: {
find: jest.fn().mockResolvedValue([new Config()])
},
...
คำตอบ
ดังนั้นปัญหาที่แท้จริงของฉันคือการล้อเลียน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
ฉันคิดว่าได้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))