繁体   English   中英

我将如何在 NestJS Jest 测试中模拟来自 TypeORM 的数据源?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM