You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NestJS Jest测试报错:无法解析非类提供者令牌依赖,求解决

NestJS Jest测试报错:POSTGRES_PROVIDERDataSource无法解析

错误信息

Nest can't resolve dependencies of the POSTGRES_PROVIDER_CategoriesRepository (?). Please make sure that the argument POSTGRES_PROVIDERDataSource at index [0] is available in the TypeOrmModule context.

    Potential solutions:
    - Is TypeOrmModule a valid NestJS module?
    - If POSTGRES_PROVIDERDataSource is a provider, is it part of the current TypeOrmModule?
    - If POSTGRES_PROVIDERDataSource is exported from a separate @Module, is that module imported within TypeOrmModule?
      @Module({
        imports: [ /* the Module containing POSTGRES_PROVIDERDataSource */ ]
      })

相关代码

测试文件 categories.service.spec.ts

import { Test, TestingModule } from '@nestjs/testing';
import { CategoriesModule } from './categories.module';

describe('CategoriesService', () => {
  let testModule: TestingModule;

  beforeEach(async () => {
    testModule = await Test.createTestingModule({
      imports:[CategoriesModule]
    }).compile();
  });

  it('should validate the app module', () => {
    expect(testModule).toBeDefined();
  });
});

CategoriesModule 配置

import { Module } from "@nestjs/common";
import { CategoriesService } from "./categories.service";
import { CategoriesRepository } from "./categories.repository";
import { DATABASE_TOKENS, SERVICE_TOKENS } from "../../src/constants";
import { TypeOrmModule } from "@nestjs/typeorm";
import { Categories } from "./models/Categories";

@Module({
    imports: [TypeOrmModule.forFeature([Categories], DATABASE_TOKENS.POSTGRES_PROVIDER)],
    providers: [{
        provide: SERVICE_TOKENS.CATEGORIES_SERVICE,
        useClass: CategoriesService
    },
    {
        provide: SERVICE_TOKENS.CATEGORIES_REPOSITORY,
        useClass: CategoriesRepository
    },
    ],
    exports: [SERVICE_TOKENS.CATEGORIES_SERVICE, SERVICE_TOKENS.CATEGORIES_REPOSITORY]
})
export class CategoriesModule { }

AppModule 导入配置

@Module({
    imports: [
        TypeOrmModule.forRootAsync({
            name: DATABASE_TOKENS.POSTGRES_PROVIDER,
            useClass: TypeOrmConfigServicePostGres,
        }),
        CategoriesModule,
    ],
    controllers: [AppController],
    providers: [AppService],
})

CategoriesService 实现

import { Injectable, Inject } from "@nestjs/common";
import { Categories } from "./models/Categories";
import { ICategoryService } from "./categories.interface";
import { FetchCategoriesDTO } from "./categories.dto";
import { SERVICE_TOKENS } from "../../src/constants";
import { ICategoryRepository } from "./categories.interface";

@Injectable()
export class CategoriesService implements ICategoryService {
    constructor(
        @Inject(SERVICE_TOKENS.CATEGORIES_REPOSITORY)
        private readonly _categoryRepository: ICategoryRepository,
    ) {}

    async fetchCategories(dto: FetchCategoriesDTO): Promise<Categories[]> {
        const { onlyActive } = dto;
        return this._categoryRepository.fetchCategories(onlyActive);
    }
}

CategoriesRepository 实现

import { Injectable } from "@nestjs/common";
import { ICategoryRepository } from "./categories.interface";
import { InjectRepository } from "@nestjs/typeorm";
import { DATABASE_TOKENS } from "../../src/constants";
import { Categories } from "./models/Categories";
import { Repository } from "typeorm";

@Injectable()
export class CategoriesRepository implements ICategoryRepository {
    constructor(
        @InjectRepository(Categories, DATABASE_TOKENS.POSTGRES_PROVIDER)
        private readonly _categories: Repository<Categories>,
    ) {}

    async fetchCategories(onlyActive: boolean): Promise<Categories[]> {
        const queryObject = onlyActive ? { isActive: true } : {};
        console.log(queryObject);
        return this._categories.find({
            where: queryObject,
        });
    }
}

错误原因

测试模块仅导入了CategoriesModule,但未初始化对应名称的TypeOrm数据源。在生产环境中,AppModule通过TypeOrmModule.forRootAsync配置了名为POSTGRES_PROVIDER的数据源,而测试上下文缺少这一步,导致Nest无法解析CategoriesRepository依赖的POSTGRES_PROVIDERDataSource。

修复方案

方案一:集成测试 - 初始化测试数据源

在测试模块中添加内存数据库的TypeOrm配置,模拟真实数据库环境:

import { Test, TestingModule } from '@nestjs/testing';
import { CategoriesModule } from './categories.module';
import { TypeOrmModule } from '@nestjs/typeorm';
import { DATABASE_TOKENS } from '../../src/constants';
import { Categories } from './models/Categories';
import { SERVICE_TOKENS } from '../../src/constants';

describe('CategoriesService', () => {
  let testModule: TestingModule;

  beforeEach(async () => {
    testModule = await Test.createTestingModule({
      imports: [
        // 初始化带指定名称的内存数据源
        TypeOrmModule.forRoot({
          name: DATABASE_TOKENS.POSTGRES_PROVIDER,
          type: 'sqlite',
          database: ':memory:',
          entities: [Categories],
          synchronize: true,
          dropSchema: true,
        }),
        CategoriesModule,
      ],
    }).compile();
  });

  it('should validate the module', () => {
    expect(testModule).toBeDefined();
  });

  it('should fetch categories correctly', async () => {
    const service = testModule.get(SERVICE_TOKENS.CATEGORIES_SERVICE);
    const categories = await service.fetchCategories({ onlyActive: false });
    expect(categories).toBeInstanceOf(Array);
  });
});

方案二:单元测试 - Mock仓库依赖

如果不需要测试数据库交互,直接Mock掉ICategoryRepository,专注于Service逻辑:

import { Test, TestingModule } from '@nestjs/testing';
import { CategoriesService } from './categories.service';
import { SERVICE_TOKENS } from '../../src/constants';
import { ICategoryRepository } from './categories.interface';

// Mock仓库的实现逻辑
const mockCategoryRepo: Partial<ICategoryRepository> = {
  fetchCategories: jest.fn().mockResolvedValue([
    { id: 1, name: '测试分类', isActive: true }
  ]),
};

describe('CategoriesService', () => {
  let service: CategoriesService;

  beforeEach(async () => {
    const module = await Test.createTestingModule({
      providers: [
        CategoriesService,
        {
          provide: SERVICE_TOKENS.CATEGORIES_REPOSITORY,
          useValue: mockCategoryRepo,
        },
      ],
    }).compile();

    service = module.get<CategoriesService>(CategoriesService);
  });

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

  it('should call repository to fetch categories', async () => {
    const result = await service.fetchCategories({ onlyActive: true });
    expect(result).toHaveLength(1);
    expect(mockCategoryRepo.fetchCategories).toHaveBeenCalledWith(true);
  });
});

内容的提问来源于stack exchange,提问作者chaithu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 21:44:53