NestJS跨包测试StockModule时GraphQLModule依赖注入失败问题
NestJS测试GraphQL联邦模块时HttpAdapterHost依赖解析失败
问题背景
我有两个独立的NestJS包,各自拥有package.json:
- 第一个是
stock包,其中的StockModule导入了配置ApolloFederationDriver的GraphQLModule - 第二个是
test包,依赖配置和stock包完全一致,尝试用Jest测试StockModule功能时,导入StockModule创建应用上下文,Nest抛出依赖解析错误,提示找不到HttpAdapterHost。已确认所有@nestjs/*版本一致,甚至直接复制stock包的node_modules/@nestjs到test包,问题依然存在。
Stock包依赖配置
{ "name": "stock", "dependencies": { "@apollo/federation": "^0.37.1", "@apollo/subgraph": "^2.1.3", "@nestjs/apollo": "^10.0.9", "@nestjs/axios": "^1.0.0", "@nestjs/common": "^8.4.7", "@nestjs/core": "^8.4.4", "@nestjs/graphql": "^10.0.22", "@nestjs/platform-express": "^8.4.4", "apollo-server-core": "^3.10.2", "apollo-server-express": "^3.10.2" } }
StockModule代码
@Module({ imports: [ GraphQLModule.forRoot<ApolloFederationDriverConfig>({ driver: ApolloFederationDriver, typePaths: [join(__dirname, '..', 'src', 'schema.gql')], playground: false, plugins: [ApolloServerPluginLandingPageLocalDefault()], }), ], }) export class StockModule { }
TestModule测试代码
import { NestFactory } from '@nestjs/core'; import { StockModule } from 'stock'; import { Module } from '@nestjs/common'; @Module({ imports: [StockModule], }) class TestModule { } describe('Stock Module ', () => { beforeAll(async () => { const app = await NestFactory.createApplicationContext(TestModule); }); });
错误信息
[Nest] 7278 - 12/02/2022, 11:00:56 AM ERROR [ExceptionHandler] Nest can't resolve dependencies of the GraphQLModule (?, GqlModuleOptions, AbstractGraphQLDriver, GraphQLTypesLoader). Please make sure that the argument HttpAdapterHost at index [0] is available in the GraphQLModule context. Potential solutions: - If HttpAdapterHost is a provider, is it part of the current GraphQLModule? - If HttpAdapterHost is exported from a separate @Module, is that module imported within GraphQLModule? @Module({ imports: [ /* the Module containing HttpAdapterHost */ ] })
解决方案
问题核心是createApplicationContext创建的是无HTTP适配器的纯应用上下文,而ApolloFederationDriver依赖HttpAdapterHost(由HTTP适配器提供),导致依赖缺失。以下两种方法可解决:
方法1:创建完整HTTP应用实例
改用NestFactory.create创建带HTTP适配器的完整应用,HttpAdapterHost会被自动注入:
describe('Stock Module ', () => { let app: INestApplication; beforeAll(async () => { app = await NestFactory.create(TestModule); await app.init(); }); afterAll(async () => { await app.close(); }); });
方法2:手动注入模拟的HttpAdapterHost
如果不想启动完整HTTP服务器,可在测试模块中手动提供HttpAdapterHost的模拟实现:
import { HttpAdapterHost } from '@nestjs/core'; @Module({ imports: [StockModule], providers: [ { provide: HttpAdapterHost, useValue: { httpAdapter: { getHttpServer: jest.fn() } // 模拟必要方法 } } ], }) class TestModule { }
内容的提问来源于stack exchange,提问作者Ohdev
相关产品推荐
相关产品推荐

