我正在尝试用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
(Any repository)
@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()
,而不是创建一个单独的存储库类,他们将提供getRepositoryToken()
,然后使用模拟工厂[链接]。我找不到一个可行的方法。
另一个解决方案建议使用内存数据库解决方案[Link]。但这感觉更像是一个hack而不是一个解决方案。
如何测试上述设置?
根据这个注释,我可以通过在测试中的提供程序中使用以下代码来实现:
providers: [
SessionService,
{ provide: SessionRepository, useClass: SessionMockRepository },
]
SessionMockRepository包含该特定存储库中所有附加函数的模拟版本:
export class SessionMockRepository extends Repository<Session> {
someFunction = async () => jest.fn();
}
目前,这对我来说是有效的,所以我接受这个。如果有更好的方法,我仍然愿意接受更多的答案。