NestJS:在单元测试中未模拟或发现 HttpService

问题描述 投票:0回答:1

我正在尝试为

@nestjs
服务编写单元测试,并且需要模拟
HttpService
。我的单元测试实现返回时出现以下错误:

TypeError: Cannot read properties of undefined (reading 'get')

在单元测试的上下文中,尽管在

@Injectable
模块中使用了
air-gateway.service
装饰器,但 httpService 从未被定义。

空中网关.service.spec.ts
import { AirGatewayService } from './air-gateway.service';
import { HttpService } from '@nestjs/axios';
import { createMock, DeepMocked } from '@golevelup/ts-jest';
import { Test, TestingModule } from '@nestjs/testing';

describe('AirGateway Service', () => {
  let service: AirGatewayService;
  let httpService: DeepMocked<HttpService>;

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [
        AirGatewayService,
        {
          provide: HttpService,
          useValue: createMock<HttpService>(),
        },
      ],
    })
      .useMocker(createMock)
      .compile();

    service = await module.get<AirGatewayService>(AirGatewayService);
    httpService = await module.get(HttpService);
  });

  afterEach(() => {
    jest.clearAllMocks();
  });

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

这里是服务的实现。我可以确认正在我的开发人员环境中成功调用端点。

空中网关.service.ts
import { Injectable } from '@nestjs/common';
import { HttpService } from '@nestjs/axios';
import { TerminusArgs } from './dto/terminus.args';
import { AirSchedules } from './models/air-schedules.model';

@Injectable()
export class AirGatewayService {
  constructor(private readonly httpService: HttpService) {}

  public async findAll(terminusArgs: TerminusArgs): Promise<AirSchedules> {
    const { data } = await firstValueFrom(
      this.httpService
        .get<GatewayResponse<AirSchedules>>(gatewayURL.href, { headers })
        .pipe(
          catchError((error: AxiosError) => {
            throw `GatewayServiceError -> findAll: an error has occurred fetching for Gateway\n${error}`;
          })
        )
    );
  }
}
  • 我已将任何 Nest、axios、jest、typescript 的依赖项更新到最新版本。

    "@nestjs/apollo": "12.0.3",
    "@nestjs/axios": "^3.0.0",
    "@nestjs/core": "10.0.3",
    "typescript": "5.1.6",

  • 我的项目有 babel.config.js,允许我在测试中运行打字稿

module.exports = {
  presets: [
    ['@babel/preset-env', { targets: { node: 'current' } }],
    '@babel/preset-typescript'
  ],
  plugins: [['@babel/plugin-proposal-decorators', { version: '2023-11' }]]
};
  • 尝试设置和删除
    jest.config.js
    文件,如下所示:
module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'node',
  moduleNameMapper: {
    axios: 'axios/dist/node/axios.cjs'
  }
}
  • 使用
    @automock/jest
    npm 包进行实验 但这对于几乎相同的错误只是在错误日志中以不同的方式表达而失败。
Automock 片段
  let service: AirGatewayService;
  let httpService: jest.Mocked<HttpService>;

  beforeAll(() => {
    const { unit, unitRef } =
      TestBed.create(AirGatewayService).compile();

    service = unit;
    httpService = unitRef.get(HttpService);
  });

失败: IdentifierNotFoundError:缺少类依赖项标识符(代码 ER010) 与指定令牌或标识符(“HttpService”)关联的依赖项无法位于 当前的测试环境。此问题与 UnitReference API 的使用有关。 请确保所提供的令牌或标识符与相应的内容之间的拼写和对应关系准确无误 注射配置。如果您使用自定义令牌,则必须确认其正确注册 在 DI 容器内

  • 在启用跟踪的情况下运行
    npx jest air-gateway.service.spec.ts
    时,我得到此跟踪。
Trace: gateway
        at GatewayService.trace [as findAll] (/Users/pingwinZloty/Projects/centrus-active/apps/gateway-subgraph/src/gateway/gateway.service.ts:41:9)
        at Object.findAll (/Users/pingwinZloty/Projects/centrus-active/apps/gateway-subgraph/src/gateway/tests/gateway.service.spec.ts:140:35)
        at Promise.then.completed (/Users/pingwinZloty/Projects/centrus-active/node_modules/jest-circus/build/utils.js:298:28)
        at new Promise (<anonymous>)
        at callAsyncCircusFn (/Users/pingwinZloty/Projects/centrus-active/node_modules/jest-circus/build/utils.js:231:10)
        at _callCircusTest (/Users/pingwinZloty/Projects/centrus-active/node_modules/jest-circus/build/run.js:316:40)
        at processTicksAndRejections (node:internal/process/task_queues:95:5)
        at _runTest (/Users/pingwinZloty/Projects/centrus-active/node_modules/jest-circus/build/run.js:252:3)
        at _runTestsForDescribeBlock (/Users/pingwinZloty/Projects/centrus-active/node_modules/jest-circus/build/run.js:126:9)
        at _runTestsForDescribeBlock (/Users/pingwinZloty/Projects/centrus-active/node_modules/jest-circus/build/run.js:121:9)
        at run (/Users/pingwinZloty/Projects/centrus-active/node_modules/jest-circus/build/run.js:71:3)
        at runAndTransformResultsToJestFormat (/Users/pingwinZloty/Projects/centrus-active/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21)
        at jestAdapter (/Users/pingwinZloty/Projects/centrus-active/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:19)
        at runTestInternal (/Users/pingwinZloty/Projects/centrus-active/node_modules/jest-runner/build/runTest.js:367:16)
        at runTest (/Users/pingwinZloty/Projects/centrus-active/node_modules/jest-runner/build/runTest.js:444:34)
typescript unit-testing axios mocking nestjs
1个回答
0
投票

尝试使用 overrideProvider 进行模拟

const module: TestingModule = await Test.createTestingModule({
  providers: [
    AirGatewayService,HttpService
  ],
})
  .overrideProvider(HttpService)
  .useValue(mockHttpService)
  .compile();

你可以像这样嘲笑你的 HttpService

export const mockHttpService ={
  get: jest.fn().mockImplementation(() => {
     return ;
  }),
}
© www.soinside.com 2019 - 2024. All rights reserved.