typescript 如何解决依赖测试NestJS包括Mongoose和Cache的问题?

eqqqjvef  于 2023-02-17  发布在  TypeScript
关注(0)|答案(1)|浏览(132)

我尝试使用已实现的Jest框架在NestJS中测试我的应用程序的控制器。问题是我的应用程序与MongoDB和CacheService有依赖关系,它们包含在Nest中,但仍需要实现。
这是我想要测试的控制器:

计算器.控制器.ts

@Controller('/calculator')
export class CalculatorController {
  constructor(
    @Inject(HISTORY_SERVICE)
    private historyService: HistoryService,
    @Inject(CACHE_SERVICE)
    private readonly cacheService: CacheService,
  ) {}
  @Get()
  getResult(
    @Query() expressionDto: ExpressionDto,
  ): Promise<CalculationResultDto> {
    const { expression } = expressionDto;
    const response = this.cacheService
      .checkInCache(expression)
      .then((result) => {
        const dto = { result: `${result}`, expression };
        const historyItem = this.historyService.create(dto);
        return historyItem;
      });
    return response;
  }
}

如您所见,我没有在此控制器中使用CalculatorService,因为计算器的算法如下:CalculatorController以表达式的形式获取请求以进行计数。表达式被传递给CacheService。在缓存中检查表达式,如果不存在,则从CacheService调用CalculatorService,并将结果返回给CalculatorController。接下来,调用HistoryService,它负责将计算结果存储在数据库中。2这对于将表达式的计算结果以正确的形式发送给用户是必要的。3数据库添加一个ID等等。
在所有操作结束时,将结果发送到客户端。
现在我们来看看测试。

计算器.控制器.规格ts

jest.mock('../calculator.service.ts');

let calculatorController: CalculatorController;
let calculatorService: CalculatorService;

beforeEach(async () => {
  const moduleRef = await Test.createTestingModule({
    imports: [HistoryModule],
    controllers: [CalculatorController],

    providers: [
      { useClass: CalculatorService, provide: CALCULATOR_SERVICE },
      {
        useClass: ExpressionCounterService,
        provide: EXPRESSION_COUNTER_SERVICE,
      },
      {
        useClass: RegExCreatorService,
        provide: REGEXP_CREATOR_SERVICE_INTERFACE,
      },
      { useClass: CacheService, provide: CACHE_SERVICE },
      { useClass: HistoryService, provide: HISTORY_SERVICE },
    ],
  }).compile();
  calculatorController =
    moduleRef.get<CalculatorController>(CalculatorController);
  calculatorService = moduleRef.get<CalculatorService>(CalculatorService);
  jest.clearAllMocks();
});

describe('getResult', () => {
  describe('when getResult is called', () => {
    beforeEach(async () => {
      await calculatorController.getResult(calculatorStub().request);
    });
    test('then it should call calculatorService', () => {
      expect(calculatorService.getResult).toBeCalledWith(
        calculatorStub().request.expression,
      );
    });
  });
});

错误

Nest can't resolve dependencies of the CacheService (?, CALCULATOR_SERVICE). Please make sure that the argument CACHE_MANAGER at index [0] is available in the RootTestModule context.

我完全模仿了真实的的计算器模块,但即使这样它也不工作。这里是我的计算器模块作为一个例子。

计算器模块ts

@Module({
  imports: [HistoryModule],
  controllers: [CalculatorController],
  providers: [
    { useClass: CalculatorService, provide: CALCULATOR_SERVICE },
    { useClass: ExpressionCounterService, provide: EXPRESSION_COUNTER_SERVICE },
    {
      useClass: RegExCreatorService,
      provide: REGEXP_CREATOR_SERVICE_INTERFACE,
    },
    { useClass: CacheService, provide: CACHE_SERVICE },
    { useClass: HistoryService, provide: HISTORY_SERVICE },
  ],
})
export class CalculatorModule {}

如果你们中有人能帮我解决这个问题,我将非常感激。以防万一,我会留下一个项目库的链接。
https://github.com/tresor13/calculator/tree/main/server/src

vybvopom

vybvopom1#

很可能你没有模仿CacheService,而是使用了真实的的类。在这种情况下,Nest尝试从类创建示例,但它有一些依赖项,这些依赖项没有在提供者列表中提供。
因此,您需要在提供者列表中添加CacheService的依赖项,或者模拟该类。

providers: [
  { useClass: CalculatorService, provide: CALCULATOR_SERVICE },
  {
    useClass: ExpressionCounterService,
    provide: EXPRESSION_COUNTER_SERVICE,
  },
  {
    useClass: RegExCreatorService,
    provide: REGEXP_CREATOR_SERVICE_INTERFACE,
  },
  { useClass: CacheService, provide: CACHE_SERVICE },
  { useClass: HistoryService, provide: HISTORY_SERVICE },
  /* dependencies of CacheService */
],

{ useValue: mockedCacheService, provide: CACHE_SERVICE }

mockCacheService只是一个简单的对象,它的每个方法都被jest.fn()模拟:

const mockedCacheService = {
  /* f1 is just a sample method in the CacheService class*/
  f1: jest.fn(),
  /* other methods */
};

useValue语法对于注入常量值、将外部库放入Nest容器或用mock对象替换真实的实现非常有用,假设您希望强制Nest使用模拟CatsService进行测试。

相关问题