我正在尝试为
@nestjs
服务编写单元测试,并且需要模拟 HttpService
。我的单元测试实现返回时出现以下错误:
TypeError: Cannot read properties of undefined (reading 'get')
在单元测试的上下文中,尽管在
@Injectable
模块中使用了 air-gateway.service
装饰器,但 httpService 从未被定义。
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();
});
});
这里是服务的实现。我可以确认正在我的开发人员环境中成功调用端点。
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 包进行实验
但这对于几乎相同的错误只是在错误日志中以不同的方式表达而失败。 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)
尝试使用 overrideProvider 进行模拟
const module: TestingModule = await Test.createTestingModule({
providers: [
AirGatewayService,HttpService
],
})
.overrideProvider(HttpService)
.useValue(mockHttpService)
.compile();
你可以像这样嘲笑你的 HttpService
export const mockHttpService ={
get: jest.fn().mockImplementation(() => {
return ;
}),
}