我将如何模拟数据源从TypeORM在NestJS Jest测试?



我正在尝试用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();
}

目前,这对我来说是有效的,所以我接受这个。如果有更好的方法,我仍然愿意接受更多的答案。

最新更新