![](/img/trans.png)
[英]How To Mock Repository, Service and Controller In NestJS (Typeorm & Jest)
[英]How would I mock the DataSource from TypeORM in NestJS Jest tests?
我正在尝试为 NestJS 中的一个小项目编写测试。 这是上下文的相关代码:
dummy.controller.ts
@Controller(UrlConstants.BASE_URL + 'dummy')
export class DummyContoller {
constructor(
private readonly sessionService: SessionService,
) { }
@Get('validateSession')
async checkValidateSession(@Query('sessionId') sessionId: string) {
const session = await this.sessionService.validateSession(sessionId);
console.log(session);
return { message: "OK" };
}
}
session.service.ts
@Injectable()
export class SessionService {
constructor(
private readonly sessionRepo: SessionRepository,
private readonly accountRepo: AccountRepository
) { }
@WithErrorBoundary(AuthCodes.UNKNOWN_LOGIN_ERROR)
async validateSession(sessionId: string) {
const session = await this.sessionRepo.findOneBy({ sessionId });
if (!session || this.isSessionExpired(session)) {
session && await this.sessionRepo.remove(session);
throw new HttpException({
code: AuthCodes.SESSION_TIMEOUT,
message: AuthMessages.SESSION_TIMEOUT
}, HttpStatus.UNAUTHORIZED)
}
return session;
}
...
}
session.repository.ts
(任何存储库)
@Injectable()
export class SessionRepository extends Repository<Session> {
constructor(private dataSource: DataSource) {
super(Session, dataSource.createEntityManager())
}
...
}
这就是我编写测试的方式(这是我第一次使用 Jest 编写测试,一般来说我在编写测试方面并没有真正的经验):
describe('DummyController', () => {
let dummyContoller: DummyContoller;
let sessionService: SessionService;
let sessionRepo: SessionRepository;
let accountRepo: AccountRepository;
beforeEach(async () => {
const module = await Test.createTestingModule({
controllers: [DummyContoller],
providers: [SessionService, SessionRepository, AccountRepository]
}).compile();
dummyContoller = module.get<DummyContoller>(DummyContoller);
sessionService = module.get<SessionService>(SessionService);
sessionRepo = module.get<SessionRepository>(SessionRepository);
accountRepo = module.get<AccountRepository>(AccountRepository);
})
describe('checkValidateSession', () => {
it('should return valid session', async () => {
const sessionId = "sessionId1";
const session = new Session();
jest.spyOn(sessionService, 'validateSession').mockImplementation(async (sessionId) => session);
expect(await dummyContoller.checkValidateSession(sessionId)).toBe(session);
})
})
})
运行测试时,我遇到:
Nest can't resolve dependencies of the SessionRepository (?). Please make sure that the argument DataSource at index [0] is available in the RootTestModule context.
Potential solutions:
- If DataSource is a provider, is it part of the current RootTestModule?
- If DataSource is exported from a separate @Module, is that module imported within RootTestModule?
@Module({
imports: [ /* the Module containing DataSource */ ]
})
我查看了这个问题,遇到了很多解决方案,但大多数解决方案都有@InjectRepository()
而不是创建单独的存储库 class ,他们会在其中提供getRepositoryToken()
然后使用模拟工厂[Link] 。 我找不到使这项工作正常进行的方法。
另一种解决方案建议使用内存数据库解决方案[链接] 。 但这感觉更像是一种破解而不是解决方案。
如何测试上述设置?
基于此评论,我能够通过在测试中的提供程序中使用以下内容来实现此功能:
providers: [
SessionService,
{ provide: SessionRepository, useClass: SessionMockRepository },
]
SessionMockRepository 包含该特定存储库中所有附加功能的模拟版本:
export class SessionMockRepository extends Repository<Session> {
someFunction = async () => jest.fn();
}
目前,这对我有用,所以我接受了。 如果有更好的方法可以做到这一点,我仍然愿意接受更多答案。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.