.NET5运行集成测试时如何启动GraphQL服务器?
问题排查与修正方案
认知正误确认
你对WebApplicationFactory<Startup>的认知是正确的:它默认会完全复用主项目的Startup.cs配置,无需重复注册服务、重复写配置逻辑,额外添加的重复配置反而可能引发服务注册冲突。
现存问题与修正点
1. ApiWebApplicationFactory泛型继承错误
你定义的泛型类继承逻辑有误,导致无法正确加载传入的TStartup(主项目Startup类)配置:
// 错误写法 public class ApiWebApplicationFactory<TStartup> : WebApplicationFactory<Startup> where TStartup : class // 正确写法,继承对应泛型类 public class ApiWebApplicationFactory<TStartup> : WebApplicationFactory<TStartup> where TStartup : class
2. 配置未注入WebHost
你构建的IConfiguration没有传递给WebHost,导致主项目中依赖配置的服务(比如DbContext、GraphQL配置)无法正确读取参数,需要在ConfigureWebHost中添加配置注入逻辑,同时确保测试项目的appsettings.json设置了「复制到输出目录:如果较新则复制」。
3. 重复注册GraphQL服务
ConfigureWebHost中重复添加的AddGraphQLServer配置和主项目Startup的注册逻辑冲突,直接删除这段配置即可。
4. GraphQL查询语法错误
你的查询语句中无参数的字段后多余添加了括号,会导致GraphQL服务器解析失败返回400 Bad Request,这是你当前报错的直接诱因,删除多余括号即可。
5. DbContext实例不统一
你单独初始化的CmsContext和WebHost DI容器中使用的CmsContext不是同一个实例,会导致测试操作的数据和接口实际使用的数据不一致,建议从工厂的服务容器中获取上下文实例。
修正后完整代码
ApiWebApplicationFactory.cs
public class ApiWebApplicationFactory<TStartup> : WebApplicationFactory<TStartup> where TStartup : class { public IConfigurationRoot Configuration { get; set; } public ApiWebApplicationFactory() { var configBuilder = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true); Configuration = configBuilder.Build(); } protected override void ConfigureWebHost(IWebHostBuilder builder) { // 注入自定义配置 builder.UseConfiguration(Configuration); } protected override void ConfigureClient(HttpClient client) { base.ConfigureClient(client); client.BaseAddress = new Uri("https://localhost"); client.Timeout = TimeSpan.FromMinutes(10); } }
OneTimeSetUp逻辑
[OneTimeSetUp] public void OneTimeSetUp() { _factory = new ApiWebApplicationFactory<Startup>(); _client = _factory.WithWebHostBuilder(builder => { builder.ConfigureServices(services => { // 替换为测试用缓存实现 services.AddScoped<ICacheRepository, MockCache>(); }); }).CreateClient(); // 从工厂DI容器获取DbContext,保证和接口使用的上下文一致 using var scope = _factory.Services.CreateScope(); _dbContext = scope.ServiceProvider.GetRequiredService<CmsContext>(); _dbContext.Database.EnsureCreated(); }
测试方法逻辑
[Test] public async Task Test() { var graphQLHttpClient = new GraphQLHttpClient( new GraphQLHttpClientOptions { EndPoint = new Uri("https://localhost/graphql") }, new NewtonsoftJsonSerializer(), _client); var request = new GraphQLRequest { // 移除无参字段的多余括号 Query = @" query GetCurrentSession { getCurrentSession { id name } }", OperationName = "GetCurrentSession" }; var response = await graphQLHttpClient.SendQueryAsync<Session>(request); // 建议先断言无GraphQL执行错误,方便后续排查 Assert.IsNull(response.Errors); // 后续业务断言 }
内容的提问来源于stack exchange,提问作者James654987
相关产品推荐
相关产品推荐

