使用 NestJS 和异步函数开玩笑
Jest with NestJS and async function
我正在尝试在 nestJS.
中测试 service
的异步函数
这个函数是异步的...基本上从数据库中获取一个值(JSON)(使用存储库 - TypeORM),当成功获取数据时,“转换”到不同的 class (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 进行测试,但没有成功......
我的问题是如何从 repository
..
模拟 findOne
函数
编辑:我正在尝试使用 @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
。
Update:我正在尝试使用 @golevelup/nestjs-testing
模拟存储库,但出于某种原因,模拟结果在服务上不起作用。
如果我仅使用 jest
模拟存储库(如下面的代码),则测试有效...所以,我认为我真正的问题是 @golevelup/nestjs-testing
.
...
provide: getRepositoryToken(Config),
useValue: {
find: jest.fn().mockResolvedValue([new Config()])
},
...
我认为 expect(await repo.findOne()).toEqual(mockedConfig);
有效是因为你嘲笑了它,所以它立即 returns。
在 expect(await service.getAppConfig()).toEqual(expectedReturn);
的情况下,您没有模拟它,因此它可能需要更多时间,因此 Promise
之前的 it
函数 returns 完全解析。
如果您模拟对 getAppConfig()
.
的调用,您从 jest 文档中发布的评论应该可以解决问题
service.getAppConfig = jest.fn(() => Promise.resolve(someFakeValue))
或
spyOn(service, 'getAppConfig').and.mockReturnValue(Promise.resolve(fakeValue))
所以,我真正的问题是我如何在 NestJS
上嘲笑 Repository
。
出于某种原因,当我使用 @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
from @roberto-correia 让我想知道我们使用包 @golevelup/nestjs-testing
.
中的 createMock
的方式是否一定有问题
原来方法超过执行时间的原因与createMock
没有实现mocking有关,没有return任何东西,除非被告知去做所以。
为了使该方法起作用,我们必须让模拟方法在测试开始时解决一些问题:
usersRepository.findOneOrFail.mockResolvedValue({ userId: 1, email: "some-random-email@email.com" });
一个基本的工作解决方案:
describe("UsersService", () => {
let usersService: UsersService;
const usersRepository = createMock<Repository<User>>();
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
UsersService,
{
provide: getRepositoryToken(User),
useValue: usersRepository,
},
}).compile();
usersService = module.get(UsersService);
});
it("should be defined", () => {
expect(usersService).toBeDefined();
});
it("finds a user", async () => {
usersRepository.findOne.mockResolvedValue({ userId: 1, email: "some-random-email@email.com" });
expect(await usersRepository.findOne()).toBe({ userId: 1, email: "some-random-email@email.com" });
});
});
我正在尝试在 nestJS.
中测试service
的异步函数
这个函数是异步的...基本上从数据库中获取一个值(JSON)(使用存储库 - TypeORM),当成功获取数据时,“转换”到不同的 class (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 进行测试,但没有成功......
我的问题是如何从 repository
..
findOne
函数
编辑:我正在尝试使用 @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
。
Update:我正在尝试使用 @golevelup/nestjs-testing
模拟存储库,但出于某种原因,模拟结果在服务上不起作用。
如果我仅使用 jest
模拟存储库(如下面的代码),则测试有效...所以,我认为我真正的问题是 @golevelup/nestjs-testing
.
...
provide: getRepositoryToken(Config),
useValue: {
find: jest.fn().mockResolvedValue([new Config()])
},
...
我认为 expect(await repo.findOne()).toEqual(mockedConfig);
有效是因为你嘲笑了它,所以它立即 returns。
在 expect(await service.getAppConfig()).toEqual(expectedReturn);
的情况下,您没有模拟它,因此它可能需要更多时间,因此 Promise
之前的 it
函数 returns 完全解析。
如果您模拟对 getAppConfig()
.
service.getAppConfig = jest.fn(() => Promise.resolve(someFakeValue))
或
spyOn(service, 'getAppConfig').and.mockReturnValue(Promise.resolve(fakeValue))
所以,我真正的问题是我如何在 NestJS
上嘲笑 Repository
。
出于某种原因,当我使用 @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
@golevelup/nestjs-testing
.
createMock
的方式是否一定有问题
原来方法超过执行时间的原因与createMock
没有实现mocking有关,没有return任何东西,除非被告知去做所以。
为了使该方法起作用,我们必须让模拟方法在测试开始时解决一些问题:
usersRepository.findOneOrFail.mockResolvedValue({ userId: 1, email: "some-random-email@email.com" });
一个基本的工作解决方案:
describe("UsersService", () => {
let usersService: UsersService;
const usersRepository = createMock<Repository<User>>();
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
UsersService,
{
provide: getRepositoryToken(User),
useValue: usersRepository,
},
}).compile();
usersService = module.get(UsersService);
});
it("should be defined", () => {
expect(usersService).toBeDefined();
});
it("finds a user", async () => {
usersRepository.findOne.mockResolvedValue({ userId: 1, email: "some-random-email@email.com" });
expect(await usersRepository.findOne()).toBe({ userId: 1, email: "some-random-email@email.com" });
});
});