Jest.js 如何模拟Nest服务的依赖关系?

zpgglvta  于 2023-08-01  发布在  Jest
关注(0)|答案(1)|浏览(128)

我在Nest中有一个服务,它导入了7个其他服务和1个存储库。我正在尝试在此服务上创建单元测试。现在,我只想测试是否定义了这个服务,以确保我的Jest设置正确。
这是我正在尝试测试的AppService。最后,我想用一个模拟存储库测试writeToProviderModel方法。

export class AppService {
  constructor(
    @InjectSentry() private readonly sentry: SentryService,
    @InjectRepository(HermesProviderEntity) private repository: Repository<HermesProviderEntity>,
    private readonly api: ApiService,
    private readonly cache: CacheService,
    private readonly config: ConfigService,
    private readonly ready: ReadyService,
    private readonly s3: S3Service,
    private readonly scheduler: SchedulerRegistry,
  ) {
    this.setupMasterCron();
    this.runPullProvider();
    this.setupCheckerCron();
  }

  //other methods.. 

  private setupCheckerCron(): void {
    const job = new CronJob('*/5 * * * *', async () => {
      if ((Date.now() - this.lastPullRunTime) / 1000 >= 300) {
        await this.api.resetLock();
        this.runPullProvider();
      }
    });
    this.scheduler.addCronJob('CHECKER_JOB', job);
    job.start();
  }

字符串
当前等级库文件如下所示:

import { Test, TestingModule } from '@nestjs/testing';
import { AppService } from './app.service';
import { AppModule } from './app.module';
import { HermesProviderEntity } from './entities/provider.entity';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ApiModule } from './api/api.module';
import { CacheModule } from './cache/cache.module';
import { ReadyModule } from './ready/ready.module';
import { S3Module } from './s3/s3.module';
import { AppController } from './app.controller';
import { Repository } from 'typeorm';

describe('AppService', () => {
  let controller: AppController;
  let service: AppService;

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      controllers: [AppController],
      imports: [
        AppModule,
        ApiModule,
        CacheModule,
        ReadyModule,
        S3Module,
        TypeOrmModule.forFeature([HermesProviderEntity]),
      ],
      providers: [AppService],
    }).compile();

    service = module.get<AppService>(AppService);
    controller = module.get(AppController);
  });

  it('should be defined', () => {
    expect(service).toBeDefined();
  });
});


我一直得到CHECKERJOB已经存在的错误,因为我的测试和实际模块都在向同一个cron作业队列添加作业。我知道我可能必须模拟所有的依赖服务,包括AppService本身,我甚至不知道如何模拟它们和存储库。我试着按照官方Nest文档中的例子,将.useMocker链接到.createTestingModule,但它告诉我这不是一个有效的方法。
任何建议都很感激!

arknldoa

arknldoa1#

您可以在测试模块中导入像{ provide: SomeService, useValue: mock }这样的提供程序,而且您确实应该这样做。
在测试运行中运行实时服务最多会导致显著的速度减慢,最坏的情况是会损坏您关心的真实的数据。
在您的情况下,它可能看起来像这样:

const module: TestingModule = await Test.createTestingModule({
  controllers: [AppController],
  imports: [
    //... snipped ...
  ],
  providers: [
    AppService,
    {
      provide: SchedulerRegistry,
      useValue: {
        addCronJob: jest.fn().mockResolvedValue(someCronJob),
        //...
      }
    },
  ],
}).compile();

字符串
在我的应用程序中,我创建了一个助手函数来使其更容易:

/**
 * Mocks a service in a test application. The mock is typed to have methods that
 * conform to the interface of the service, or may be omitted if they
 * are unused in the test.
 *
 * Example:
 *
 *     app = await Test.createTestingModule({
 *       providers: [
 *         FooService,
 *         mockService(BarService),
 *         mockService(BazService, {
 *            doSomething: () => 'mocked return value'
 *         }
 *       ],
 *     }).compile()
 *
 */
export function mockService<T extends new (...args: unknown[]) => unknown>(
  module: T,
  mock: Partial<InstanceType<T>> = {},
): {
  provide: T
  useValue: Partial<InstanceType<T>>
} {
  return {
    provide: module,
    useValue: mock,
  }
}


很方便的。

相关问题