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

使用createTestingModule时如何获取动态模块的PrismaService实例?

问题描述

我有一个全局动态模块 PrismaModule,定义如下:

// prisma.module.ts
import { DynamicModule, Global, Module } from '@nestjs/common'
import { PrismaService } from 'nestjs-prisma'

@Global()
@Module({})
export class PrismaModule {
  static register(options: {
    databaseUrl: string
  }): DynamicModule {
    return {
      module: PrismaModule,
      providers: [
        {
          provide: PrismaService,
          useFactory: () =>
            new PrismaService({
              prismaOptions: {
                datasources: {
                  db: {
                    url: options.databaseUrl,
                  },
                },
              },
            }),
        },
      ],
      exports: [PrismaService],
    }
  }
}

现在我用 Test.createTestingModule 测试非顶级模块 MyModule,该模块依赖这个全局动态模块。我按照技巧重写了模块引用:

// app.module.ts

export const prismaModule = PrismaModule.register({
  databaseUrl: process.env.DB_URL,
})

@Module({
  imports: [
    // ...
    prismaModule,
    // ...
  ],
})
export class AppModule {
  constructor() {}
}

测试代码如下:

// my-module.test.ts

import { prismaModule } from '../app.module'

// ...

const mockPrismaModule = PrismaModule.register({
  databaseUrl: "<some connection string>",
})

const moduleRef = await Test.createTestingModule({
  imports: [prismaModule],
  controllers: [MyController],
  providers: [MyService],
})
  .overrideModule(prismaModule)
  .useModule(mockPrismaModule)
  .compile()

const prismaService = mockPrismaModule.<...>

我想获取 mockPrismaModule 在 register() 过程中创建的 PrismaService 实例,试过用 mockPrismaModule.get(PrismaService),但它不像 Test.createTestingModule() 的返回结果那样能调用 get 方法,请问有没有办法实现?


解决方法

你不能直接从 mockPrismaModule(也就是 register 返回的动态模块对象)获取实例,因为它只是模块的元数据定义,不是已经实例化的模块引用。正确的做法是从编译后的 moduleRef 里获取:

const prismaService = moduleRef.get(PrismaService);

因为你已经用 overrideModule 把原模块替换成了 mockPrismaModule,编译后的测试模块里的 PrismaService 就是你通过 mockPrismaModule 配置创建的实例。

如果需要提前创建 mock 实例并注入(比如用 jest mock),可以换一种更直接的方式:直接在测试模块里覆盖 PrismaService 的提供者,而不是替换整个模块:

// 先创建mock实例
const mockPrismaService = new PrismaService({
  prismaOptions: {
    datasources: {
      db: {
        url: "<some connection string>",
      },
    },
  },
});

const moduleRef = await Test.createTestingModule({
  imports: [prismaModule],
  controllers: [MyController],
  providers: [MyService],
})
  .overrideProvider(PrismaService)
  .useValue(mockPrismaService)
  .compile();

// 这里获取的就是你提前创建的mock实例
const prismaService = moduleRef.get(PrismaService);

这种方式能让你完全控制 PrismaService 的实例,操作起来也更灵活。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 02:55:31