diff --git a/dictionary.txt b/dictionary.txt
index dd1be91d592..344189d6d45 100644
--- a/dictionary.txt
+++ b/dictionary.txt
@@ -13,8 +13,6 @@ anthropics
Antiforgery
apphost
appsettings
-ASPDEPR004
-ASPDEPR008
aspnet
aspnetcore
Astromech
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
index ac52199e192..8c04731c650 100644
--- a/src/Directory.Build.props
+++ b/src/Directory.Build.props
@@ -17,7 +17,7 @@
true
- NU1901;NU1902;NU1903;NU1904;ASPDEPR004;ASPDEPR008
+ NU1901;NU1902;NU1903;NU1904
diff --git a/src/HotChocolate/Adapters/test/Adapters.Mcp.Tests/CoreIntegrationTests.cs b/src/HotChocolate/Adapters/test/Adapters.Mcp.Tests/CoreIntegrationTests.cs
index 53d9a48ecf6..6a4a4c8583a 100644
--- a/src/HotChocolate/Adapters/test/Adapters.Mcp.Tests/CoreIntegrationTests.cs
+++ b/src/HotChocolate/Adapters/test/Adapters.Mcp.Tests/CoreIntegrationTests.cs
@@ -8,9 +8,9 @@
using HotChocolate.Types.Descriptors;
using HotChocolate.Types.Descriptors.Configurations;
using Microsoft.AspNetCore.Builder;
-using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
using Microsoft.IdentityModel.Tokens;
using ModelContextProtocol.Client;
using ModelContextProtocol.Protocol;
@@ -29,26 +29,24 @@ await storage.AddOrUpdateToolAsync(
new OperationToolDefinition(
Utf8GraphQLParser.Parse("query GetBooks { books { title } }")),
TestContext.Current.CancellationToken);
- var builder = new WebHostBuilder()
- .ConfigureServices(
- services => services
- .AddRouting()
- .AddGraphQL("NamedSchema")
- .AddAuthorization()
- .AddQueryType()
- .AddMutationType()
- .AddInterfaceType()
- .AddUnionType()
- .AddObjectType()
- .AddObjectType()
- .AddMcp()
- .AddMcpStorage(storage))
- .Configure(
- app => app
- .UseRouting()
- .UseEndpoints(endpoints => endpoints.MapGraphQLMcp()));
- var server = new TestServer(builder);
- var mcpClient = await CreateMcpClientAsync(server.CreateClient());
+ var webAppBuilder = WebApplication.CreateSlimBuilder();
+ webAppBuilder.WebHost.UseTestServer();
+ webAppBuilder.Services
+ .AddRouting()
+ .AddGraphQL("NamedSchema")
+ .AddAuthorization()
+ .AddQueryType()
+ .AddMutationType()
+ .AddInterfaceType()
+ .AddUnionType()
+ .AddObjectType()
+ .AddObjectType()
+ .AddMcp()
+ .AddMcpStorage(storage);
+ await using var webApp = webAppBuilder.Build();
+ webApp.MapGraphQLMcp();
+ webApp.Start();
+ var mcpClient = await CreateMcpClientAsync(webApp.GetTestClient());
// act
var tools = await mcpClient.ListToolsAsync(cancellationToken: TestContext.Current.CancellationToken);
@@ -66,31 +64,26 @@ await storage.AddOrUpdateToolAsync(
new OperationToolDefinition(
Utf8GraphQLParser.Parse("query GetBooks { books { title } }")),
TestContext.Current.CancellationToken);
- var builder = new WebHostBuilder()
- .ConfigureServices(
- services =>
- {
- services
- .AddRouting()
- .AddGraphQL("NamedSchema")
- .AddAuthorization()
- .AddQueryType()
- .AddMutationType()
- .AddInterfaceType()
- .AddUnionType()
- .AddObjectType()
- .AddObjectType()
- .AddMcp();
- services
- .AddOptions("NamedSchema")
- .PostConfigure(setup => setup.StorageFactory = _ => storage);
- })
- .Configure(
- app => app
- .UseRouting()
- .UseEndpoints(endpoints => endpoints.MapGraphQLMcp()));
- using var server = new TestServer(builder);
- var mcpClient = await CreateMcpClientAsync(server.CreateClient());
+ var webAppBuilder = WebApplication.CreateSlimBuilder();
+ webAppBuilder.WebHost.UseTestServer();
+ webAppBuilder.Services
+ .AddRouting()
+ .AddGraphQL("NamedSchema")
+ .AddAuthorization()
+ .AddQueryType()
+ .AddMutationType()
+ .AddInterfaceType()
+ .AddUnionType()
+ .AddObjectType()
+ .AddObjectType()
+ .AddMcp();
+ webAppBuilder.Services
+ .AddOptions("NamedSchema")
+ .PostConfigure(setup => setup.StorageFactory = _ => storage);
+ await using var webApp = webAppBuilder.Build();
+ webApp.MapGraphQLMcp();
+ webApp.Start();
+ var mcpClient = await CreateMcpClientAsync(webApp.GetTestClient());
// act
var tools = await mcpClient.ListToolsAsync(cancellationToken: TestContext.Current.CancellationToken);
@@ -103,19 +96,16 @@ await storage.AddOrUpdateToolAsync(
public void MapGraphQLMcp_Should_Throw_When_AddMcpNotCalled()
{
// arrange
- var builder = new WebHostBuilder()
- .ConfigureServices(
- services => services
- .AddRouting()
- .AddGraphQL()
- .AddQueryType())
- .Configure(
- app => app
- .UseRouting()
- .UseEndpoints(endpoints => endpoints.MapGraphQLMcp()));
+ var webAppBuilder = WebApplication.CreateSlimBuilder();
+ webAppBuilder.WebHost.UseTestServer();
+ webAppBuilder.Services
+ .AddRouting()
+ .AddGraphQL()
+ .AddQueryType();
+ var webApp = webAppBuilder.Build();
// act
- var exception = Assert.Throws(() => new TestServer(builder));
+ var exception = Assert.Throws(() => webApp.MapGraphQLMcp());
// assert
Assert.Equal(
@@ -128,37 +118,28 @@ public void MapGraphQLMcp_Should_NotBuildSchema_When_Mapping()
{
// arrange
var schemaBuilt = false;
- var schemaBuiltWhileMapping = false;
- var builder = new WebHostBuilder()
- .ConfigureServices(
- services => services
- .AddRouting()
- .AddGraphQLServer()
- .ConfigureSchemaServices(_ => schemaBuilt = true)
- .AddAuthorization()
- .AddQueryType()
- .AddMutationType()
- .AddInterfaceType()
- .AddUnionType()
- .AddObjectType()
- .AddObjectType()
- .AddMcp()
- .AddMcpStorage(new TestMcpStorage()))
- .Configure(
- app => app
- .UseRouting()
- .UseEndpoints(
- endpoints =>
- {
- endpoints.MapGraphQLMcp();
- schemaBuiltWhileMapping = schemaBuilt;
- }));
+ var webAppBuilder = WebApplication.CreateSlimBuilder();
+ webAppBuilder.WebHost.UseTestServer();
+ webAppBuilder.Services
+ .AddRouting()
+ .AddGraphQLServer()
+ .ConfigureSchemaServices(_ => schemaBuilt = true)
+ .AddAuthorization()
+ .AddQueryType()
+ .AddMutationType()
+ .AddInterfaceType()
+ .AddUnionType()
+ .AddObjectType()
+ .AddObjectType()
+ .AddMcp()
+ .AddMcpStorage(new TestMcpStorage());
+ var webApp = webAppBuilder.Build();
// act
- _ = new TestServer(builder);
+ webApp.MapGraphQLMcp();
// assert
- Assert.False(schemaBuiltWhileMapping);
+ Assert.False(schemaBuilt);
}
[Fact]
@@ -174,21 +155,19 @@ await File.ReadAllTextAsync(
TestContext.Current.CancellationToken))),
TestContext.Current.CancellationToken);
var typeModule = new TestTypeModule();
- var builder = new WebHostBuilder()
- .ConfigureServices(
- services => services
- .AddRouting()
- .AddGraphQL()
- .AddTypeModule(_ => typeModule)
- .AddMcp()
- .AddMcpStorage(storage))
- .Configure(
- app => app
- .UseRouting()
- .UseEndpoints(endpoints => endpoints.MapGraphQLMcp()));
- var server = new TestServer(builder);
- var mcpClient1 = await CreateMcpClientAsync(server.CreateClient());
- var mcpClient2 = await CreateMcpClientAsync(server.CreateClient());
+ var webAppBuilder = WebApplication.CreateSlimBuilder();
+ webAppBuilder.WebHost.UseTestServer();
+ webAppBuilder.Services
+ .AddRouting()
+ .AddGraphQL()
+ .AddTypeModule(_ => typeModule)
+ .AddMcp()
+ .AddMcpStorage(storage);
+ await using var webApp = webAppBuilder.Build();
+ webApp.MapGraphQLMcp();
+ webApp.Start();
+ var mcpClient1 = await CreateMcpClientAsync(webApp.GetTestClient());
+ var mcpClient2 = await CreateMcpClientAsync(webApp.GetTestClient());
var listChangedResetEvent1 = new ManualResetEventSlim(false);
var listChangedResetEvent2 = new ManualResetEventSlim(false);
mcpClient1.RegisterNotificationHandler(
@@ -213,7 +192,7 @@ await File.ReadAllTextAsync(
if (listChangedResetEvent1.Wait(TimeSpan.FromSeconds(5), TestContext.Current.CancellationToken))
{
- var mcpClient3 = await CreateMcpClientAsync(server.CreateClient());
+ var mcpClient3 = await CreateMcpClientAsync(webApp.GetTestClient());
updatedTools = await mcpClient3.ListToolsAsync(cancellationToken: TestContext.Current.CancellationToken);
}
@@ -247,54 +226,52 @@ protected override Task CreateTestServerAsync(
Action? configureMcpServerOptions = null,
Action? configureMcpServer = null)
{
- var builder = new WebHostBuilder()
- .ConfigureServices(
- services =>
- {
- services
- .AddLogging()
- .AddRouting()
- .AddAuthentication()
- .AddJwtBearer(
- o => o.TokenValidationParameters =
- new TokenValidationParameters
- {
- ValidIssuer = TokenIssuer,
- ValidAudience = TokenAudience,
- IssuerSigningKey = TokenKey
- });
+ var webAppBuilder = WebApplication.CreateSlimBuilder();
+ webAppBuilder.WebHost.UseTestServer();
+ webAppBuilder.Services
+ .AddLogging()
+ .AddRouting()
+ .AddAuthentication()
+ .AddJwtBearer(
+ o => o.TokenValidationParameters =
+ new TokenValidationParameters
+ {
+ ValidIssuer = TokenIssuer,
+ ValidAudience = TokenAudience,
+ IssuerSigningKey = TokenKey
+ });
- var builder =
- services
- .AddGraphQLServer()
- .ModifyCostOptions(o => o.DefaultListSize = 1)
- .AddAuthorization()
- .AddMcp(configureMcpServerOptions, configureMcpServer)
- .AddMcpStorage(storage)
- .AddQueryType()
- .AddMutationType()
- .AddInterfaceType()
- .AddUnionType()
- .AddObjectType()
- .AddObjectType();
+ var graphqlBuilder =
+ webAppBuilder.Services
+ .AddGraphQLServer()
+ .ModifyCostOptions(o => o.DefaultListSize = 1)
+ .AddAuthorization()
+ .AddMcp(configureMcpServerOptions, configureMcpServer)
+ .AddMcpStorage(storage)
+ .AddQueryType()
+ .AddMutationType()
+ .AddInterfaceType()
+ .AddUnionType()
+ .AddObjectType()
+ .AddObjectType();
- if (additionalTypes is not null)
- {
- builder.AddTypes(additionalTypes);
- }
+ if (additionalTypes is not null)
+ {
+ graphqlBuilder.AddTypes(additionalTypes);
+ }
- if (diagnosticEventListener is not null)
- {
- builder.AddDiagnosticEventListener(_ => diagnosticEventListener);
- }
- })
- .Configure(
- app => app
- .UseRouting()
- .UseAuthentication()
- .UseEndpoints(endpoints => endpoints.MapGraphQLMcp()));
+ if (diagnosticEventListener is not null)
+ {
+ graphqlBuilder.AddDiagnosticEventListener(_ => diagnosticEventListener);
+ }
+
+ var app = webAppBuilder.Build();
+ app.UseRouting();
+ app.UseAuthentication();
+ app.MapGraphQLMcp();
+ app.Start();
- return Task.FromResult(new TestServer(builder));
+ return Task.FromResult(app.GetTestServer());
}
private sealed class TestTypeModule : TypeModule
diff --git a/src/HotChocolate/Adapters/test/Adapters.Mcp.Tests/FusionIntegrationTests.cs b/src/HotChocolate/Adapters/test/Adapters.Mcp.Tests/FusionIntegrationTests.cs
index 402aa9fa554..71d6a9ea922 100644
--- a/src/HotChocolate/Adapters/test/Adapters.Mcp.Tests/FusionIntegrationTests.cs
+++ b/src/HotChocolate/Adapters/test/Adapters.Mcp.Tests/FusionIntegrationTests.cs
@@ -13,9 +13,9 @@
using HotChocolate.Types;
using HotChocolate.Types.Mutable;
using Microsoft.AspNetCore.Builder;
-using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
using Microsoft.IdentityModel.Tokens;
using ModelContextProtocol.Client;
using ModelContextProtocol.Protocol;
@@ -34,7 +34,7 @@ await storage.AddOrUpdateToolAsync(
new OperationToolDefinition(
Utf8GraphQLParser.Parse("query GetBooks { books { title } }")),
TestContext.Current.CancellationToken);
- var subgraph = CreateSubgraph([]);
+ await using var subgraph = StartSubgraph([]);
var schemaDocument = await subgraph.Services.GetSchemaAsync(
cancellationToken: TestContext.Current.CancellationToken);
var schemaComposer =
@@ -43,25 +43,20 @@ [new SourceSchemaText(schemaDocument.Name, schemaDocument.ToString())],
new SchemaComposerOptions(),
new CompositionLog());
var result = schemaComposer.Compose();
- var builder = new WebHostBuilder()
- .ConfigureServices(
- services =>
- {
- services
- .AddRouting()
- .AddGraphQLGatewayServer("NamedSchema")
- .AddInMemoryConfiguration(result.Value.ToSyntaxNode())
- .AddMcp();
- services
- .AddOptions("NamedSchema")
- .PostConfigure(setup => setup.StorageFactory = _ => storage);
- })
- .Configure(
- app => app
- .UseRouting()
- .UseEndpoints(endpoints => endpoints.MapGraphQLMcp()));
- using var server = new TestServer(builder);
- var mcpClient = await CreateMcpClientAsync(server.CreateClient());
+ var webAppBuilder = WebApplication.CreateSlimBuilder();
+ webAppBuilder.WebHost.UseTestServer();
+ webAppBuilder.Services
+ .AddRouting()
+ .AddGraphQLGatewayServer("NamedSchema")
+ .AddInMemoryConfiguration(result.Value.ToSyntaxNode())
+ .AddMcp();
+ webAppBuilder.Services
+ .AddOptions("NamedSchema")
+ .PostConfigure(setup => setup.StorageFactory = _ => storage);
+ await using var webApp = webAppBuilder.Build();
+ webApp.MapGraphQLMcp();
+ webApp.Start();
+ var mcpClient = await CreateMcpClientAsync(webApp.GetTestClient());
// act
var tools = await mcpClient.ListToolsAsync(cancellationToken: TestContext.Current.CancellationToken);
@@ -82,7 +77,7 @@ await File.ReadAllTextAsync(
"__resources__/GetBooksWithTitle1.graphql",
TestContext.Current.CancellationToken))),
TestContext.Current.CancellationToken);
- var subgraph = CreateSubgraph([]);
+ await using var subgraph = StartSubgraph([]);
var schemaDocument = await subgraph.Services.GetSchemaAsync(
cancellationToken: TestContext.Current.CancellationToken);
var schemaComposer =
@@ -97,21 +92,19 @@ [new SourceSchemaText(schemaDocument.Name, schemaDocument.ToString())],
schema.ToSyntaxNode(),
new JsonDocumentOwner(JsonDocument.Parse("{ }"), new EmptyMemoryOwner()));
var configProvider = new TestFusionConfigurationProvider(initialConfig);
- var builder = new WebHostBuilder()
- .ConfigureServices(
- services => services
- .AddRouting()
- .AddGraphQLGatewayServer()
- .AddConfigurationProvider(_ => configProvider)
- .AddMcp()
- .AddMcpStorage(storage))
- .Configure(
- app => app
- .UseRouting()
- .UseEndpoints(endpoints => endpoints.MapGraphQLMcp()));
- var server = new TestServer(builder);
- var mcpClient1 = await CreateMcpClientAsync(server.CreateClient());
- var mcpClient2 = await CreateMcpClientAsync(server.CreateClient());
+ var webAppBuilder = WebApplication.CreateSlimBuilder();
+ webAppBuilder.WebHost.UseTestServer();
+ webAppBuilder.Services
+ .AddRouting()
+ .AddGraphQLGatewayServer()
+ .AddConfigurationProvider(_ => configProvider)
+ .AddMcp()
+ .AddMcpStorage(storage);
+ await using var webApp = webAppBuilder.Build();
+ webApp.MapGraphQLMcp();
+ webApp.Start();
+ var mcpClient1 = await CreateMcpClientAsync(webApp.GetTestClient());
+ var mcpClient2 = await CreateMcpClientAsync(webApp.GetTestClient());
var listChangedResetEvent1 = new ManualResetEventSlim(false);
var listChangedResetEvent2 = new ManualResetEventSlim(false);
mcpClient1.RegisterNotificationHandler(
@@ -141,7 +134,7 @@ [new SourceSchemaText(schemaDocument.Name, schemaDocument.ToString())],
if (listChangedResetEvent1.Wait(TimeSpan.FromSeconds(5), TestContext.Current.CancellationToken))
{
- var mcpClient3 = await CreateMcpClientAsync(server.CreateClient());
+ var mcpClient3 = await CreateMcpClientAsync(webApp.GetTestClient());
updatedTools = await mcpClient3.ListToolsAsync(cancellationToken: TestContext.Current.CancellationToken);
}
@@ -175,7 +168,7 @@ protected override async Task CreateTestServerAsync(
Action? configureMcpServerOptions = null,
Action? configureMcpServer = null)
{
- var subgraph = CreateSubgraph(additionalTypes);
+ var subgraph = StartSubgraph(additionalTypes);
var schemaDocument = await subgraph.Services.GetSchemaAsync();
var schemaComposer =
new SchemaComposer(
@@ -184,91 +177,87 @@ [new SourceSchemaText(schemaDocument.Name, schemaDocument.ToString())],
new CompositionLog());
var result = schemaComposer.Compose();
- var builder = new WebHostBuilder()
- .ConfigureServices(
- services =>
- {
- services
- .AddHeaderPropagation(options => options.Headers.Add("Authorization"))
- .AddLogging()
- .AddRouting()
- .AddAuthentication();
-
- services
- .AddHttpClient(schemaDocument.Name)
- .AddHeaderPropagation()
- .ConfigurePrimaryHttpMessageHandler(() => subgraph.CreateHandler());
-
- var builder =
- services
- .AddGraphQLGatewayServer()
- .ModifyRequestOptions(o => o.IncludeExceptionDetails = true)
- .AddInMemoryConfiguration(result.Value.ToSyntaxNode())
- .AddHttpClientConfiguration(
- schemaDocument.Name,
- new Uri("http://localhost:5000/graphql"))
- .AddMcp(configureMcpServerOptions, configureMcpServer)
- .AddMcpStorage(storage);
-
- if (diagnosticEventListener is not null)
- {
- builder.AddDiagnosticEventListener(_ => diagnosticEventListener);
- }
- })
- .Configure(
- app => app
- .UseRouting()
- .UseHeaderPropagation()
- .UseAuthentication()
- .UseEndpoints(endpoints => endpoints.MapGraphQLMcp()));
-
- return new TestServer(builder);
+ var webAppBuilder = WebApplication.CreateSlimBuilder();
+ webAppBuilder.WebHost.UseTestServer();
+ webAppBuilder.Services
+ .AddHeaderPropagation(options => options.Headers.Add("Authorization"))
+ .AddLogging()
+ .AddRouting()
+ .AddAuthentication();
+
+ webAppBuilder.Services
+ .AddHttpClient(schemaDocument.Name)
+ .AddHeaderPropagation()
+ .ConfigurePrimaryHttpMessageHandler(subgraph.GetTestServer().CreateHandler);
+
+ var gatewayBuilder =
+ webAppBuilder.Services
+ .AddGraphQLGatewayServer()
+ .ModifyRequestOptions(o => o.IncludeExceptionDetails = true)
+ .AddInMemoryConfiguration(result.Value.ToSyntaxNode())
+ .AddHttpClientConfiguration(
+ schemaDocument.Name,
+ new Uri("http://localhost:5000/graphql"))
+ .AddMcp(configureMcpServerOptions, configureMcpServer)
+ .AddMcpStorage(storage);
+
+ if (diagnosticEventListener is not null)
+ {
+ gatewayBuilder.AddDiagnosticEventListener(_ => diagnosticEventListener);
+ }
+
+ var app = webAppBuilder.Build();
+ app.UseRouting();
+ app.UseHeaderPropagation();
+ app.UseAuthentication();
+ app.MapGraphQLMcp();
+ app.Start();
+
+ return app.GetTestServer();
}
- private static TestServer CreateSubgraph(ITypeDefinition[]? additionalTypes)
+ private static WebApplication StartSubgraph(ITypeDefinition[]? additionalTypes)
{
- var builder = new WebHostBuilder()
- .ConfigureServices(
- services =>
- {
- services
- .AddLogging()
- .AddRouting()
- .AddAuthentication()
- .AddJwtBearer(
- o => o.TokenValidationParameters =
- new TokenValidationParameters
- {
- ValidIssuer = TokenIssuer,
- ValidAudience = TokenAudience,
- IssuerSigningKey = TokenKey
- });
-
- var builder =
- services
- .AddGraphQLServer()
- .AddSourceSchemaDefaults()
- .ModifyCostOptions(o => o.DefaultListSize = 1)
- .AddAuthorization()
- .AddQueryType()
- .AddMutationType()
- .AddInterfaceType()
- .AddUnionType()
- .AddObjectType()
- .AddObjectType();
-
- if (additionalTypes is not null)
+ var webAppBuilder = WebApplication.CreateSlimBuilder();
+ webAppBuilder.WebHost.UseTestServer();
+ webAppBuilder.Services
+ .AddLogging()
+ .AddRouting()
+ .AddAuthentication()
+ .AddJwtBearer(
+ o => o.TokenValidationParameters =
+ new TokenValidationParameters
{
- builder.AddTypes(additionalTypes);
- }
- })
- .Configure(
- app => app
- .UseRouting()
- .UseAuthentication()
- .UseEndpoints(endpoints => endpoints.MapGraphQL()));
-
- return new TestServer(builder);
+ ValidIssuer = TokenIssuer,
+ ValidAudience = TokenAudience,
+ IssuerSigningKey = TokenKey
+ });
+
+ var graphqlBuilder =
+ webAppBuilder.Services
+ .AddGraphQLServer()
+ .AddSourceSchemaDefaults()
+ .ModifyCostOptions(o => o.DefaultListSize = 1)
+ .AddAuthorization()
+ .AddQueryType()
+ .AddMutationType()
+ .AddInterfaceType()
+ .AddUnionType()
+ .AddObjectType()
+ .AddObjectType();
+
+ if (additionalTypes is not null)
+ {
+ graphqlBuilder.AddTypes(additionalTypes);
+ }
+
+ var app = webAppBuilder.Build();
+ app.UseRouting();
+ app.UseAuthentication();
+ app.MapGraphQL();
+ app.Start();
+
+ return app;
}
private sealed class TestFusionConfigurationProvider(FusionConfiguration initialConfig)
diff --git a/src/HotChocolate/Adapters/test/Adapters.OpenApi.Tests/Endpoints/FusionHttpEndpointIntegrationTests.cs b/src/HotChocolate/Adapters/test/Adapters.OpenApi.Tests/Endpoints/FusionHttpEndpointIntegrationTests.cs
index 64b2656402c..2fb15c8dcfa 100644
--- a/src/HotChocolate/Adapters/test/Adapters.OpenApi.Tests/Endpoints/FusionHttpEndpointIntegrationTests.cs
+++ b/src/HotChocolate/Adapters/test/Adapters.OpenApi.Tests/Endpoints/FusionHttpEndpointIntegrationTests.cs
@@ -8,9 +8,9 @@
using HotChocolate.Fusion.Options;
using HotChocolate.Language;
using Microsoft.AspNetCore.Builder;
-using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
using Xunit.Sdk;
namespace HotChocolate.Adapters.OpenApi;
@@ -90,31 +90,26 @@ query GetUsers @http(method: GET, route: "/users") {
}
}
""");
- var builder = new WebHostBuilder()
- .ConfigureServices(services =>
- {
- services.AddRouting();
- services.AddHttpClient("A")
- .ConfigurePrimaryHttpMessageHandler(_subgraph.CreateHandler);
- services.AddGraphQLGatewayServer("NamedSchema")
- .AddInMemoryConfiguration(_compositeSchema)
- .AddHttpClientConfiguration("A", new Uri("http://localhost:5000/graphql"))
- .AddOpenApi();
- services.AddOptions("NamedSchema")
- .PostConfigure(setup => setup.StorageFactory = _ => storage);
- services.AddOpenApi(options => options.AddGraphQLTransformer());
- })
- .Configure(app =>
- {
- app.UseRouting();
- app.UseEndpoints(endpoints =>
- {
- endpoints.MapOpenApi();
- endpoints.MapOpenApiEndpoints();
- });
- });
- using var server = new TestServer(builder);
- var client = server.CreateClient();
+ var webAppBuilder = WebApplication.CreateSlimBuilder();
+ webAppBuilder.WebHost.UseTestServer();
+ webAppBuilder.Services.AddRouting();
+ webAppBuilder.Services
+ .AddHttpClient("A")
+ .ConfigurePrimaryHttpMessageHandler(_subgraph.CreateHandler);
+ webAppBuilder.Services
+ .AddGraphQLGatewayServer("NamedSchema")
+ .AddInMemoryConfiguration(_compositeSchema)
+ .AddHttpClientConfiguration("A", new Uri("http://localhost:5000/graphql"))
+ .AddOpenApi();
+ webAppBuilder.Services
+ .AddOptions("NamedSchema")
+ .PostConfigure(setup => setup.StorageFactory = _ => storage);
+ webAppBuilder.Services.AddOpenApi(options => options.AddGraphQLTransformer());
+ await using var webApp = webAppBuilder.Build();
+ webApp.MapOpenApi();
+ webApp.MapOpenApiEndpoints();
+ webApp.Start();
+ var client = webApp.GetTestClient();
// act
var response = await client.GetAsync("/users", TestContext.Current.CancellationToken);
@@ -131,28 +126,25 @@ query GetUsers @http(method: GET, route: "/users") {
public void MapOpenApiEndpoints_Should_NotResolveSchemaName_When_MultipleNamedSchemasRegistered()
{
// arrange
- var builder = new WebHostBuilder()
- .ConfigureServices(services =>
- {
- services.AddRouting();
-
- foreach (var schemaName in new[] { "alpha", "beta" })
- {
- services.AddGraphQLGatewayServer(schemaName)
- .AddInMemoryConfiguration(_compositeSchema)
- .AddOpenApi();
- services.AddOptions(schemaName)
- .PostConfigure(setup => setup.StorageFactory = _ => new TestOpenApiDefinitionStorage());
- }
- })
- .Configure(app =>
- {
- app.UseRouting();
- app.UseEndpoints(endpoints => endpoints.MapOpenApiEndpoints());
- });
+ var webAppBuilder = WebApplication.CreateSlimBuilder();
+ webAppBuilder.WebHost.UseTestServer();
+ webAppBuilder.Services.AddRouting();
+
+ foreach (var schemaName in new[] { "alpha", "beta" })
+ {
+ webAppBuilder.Services
+ .AddGraphQLGatewayServer(schemaName)
+ .AddInMemoryConfiguration(_compositeSchema)
+ .AddOpenApi();
+ webAppBuilder.Services
+ .AddOptions(schemaName)
+ .PostConfigure(setup => setup.StorageFactory = _ => new TestOpenApiDefinitionStorage());
+ }
+
+ var webApp = webAppBuilder.Build();
// act
- var exception = Assert.Throws(() => new TestServer(builder));
+ var exception = Assert.Throws(() => webApp.MapOpenApiEndpoints());
// assert
Assert.Equal(
diff --git a/src/HotChocolate/Adapters/test/Adapters.OpenApi.Tests/Endpoints/HttpEndpointIntegrationTests.cs b/src/HotChocolate/Adapters/test/Adapters.OpenApi.Tests/Endpoints/HttpEndpointIntegrationTests.cs
index 435f2712c62..011849d0d18 100644
--- a/src/HotChocolate/Adapters/test/Adapters.OpenApi.Tests/Endpoints/HttpEndpointIntegrationTests.cs
+++ b/src/HotChocolate/Adapters/test/Adapters.OpenApi.Tests/Endpoints/HttpEndpointIntegrationTests.cs
@@ -3,9 +3,9 @@
using System.Text.Json;
using HotChocolate.Adapters.OpenApi.Configuration;
using Microsoft.AspNetCore.Builder;
-using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
namespace HotChocolate.Adapters.OpenApi;
@@ -40,23 +40,19 @@ query GetUsers @http(method: GET, route: "/users") {
}
}
""");
- var builder = new WebHostBuilder()
- .ConfigureServices(services =>
- {
- services.AddRouting();
- services.AddGraphQLServer("NamedSchema")
- .ModifyCostOptions(o => o.DefaultListSize = 1)
- .AddOpenApi()
- .AddOpenApiDefinitionStorage(storage)
- .AddBasicServer();
- })
- .Configure(app =>
- {
- app.UseRouting();
- app.UseEndpoints(endpoints => endpoints.MapOpenApiEndpoints());
- });
- var server = new TestServer(builder);
- var client = server.CreateClient();
+ var webAppBuilder = WebApplication.CreateSlimBuilder();
+ webAppBuilder.WebHost.UseTestServer();
+ webAppBuilder.Services.AddRouting();
+ webAppBuilder.Services
+ .AddGraphQLServer("NamedSchema")
+ .ModifyCostOptions(o => o.DefaultListSize = 1)
+ .AddOpenApi()
+ .AddOpenApiDefinitionStorage(storage)
+ .AddBasicServer();
+ await using var webApp = webAppBuilder.Build();
+ webApp.MapOpenApiEndpoints();
+ webApp.Start();
+ var client = webApp.GetTestClient();
// act
var response = await client.GetAsync("/users", TestContext.Current.CancellationToken);
@@ -77,29 +73,23 @@ query GetUsers @http(method: GET, route: "/users") {
}
}
""");
- var builder = new WebHostBuilder()
- .ConfigureServices(services =>
- {
- services.AddRouting();
- services.AddGraphQLServer("NamedSchema")
- .ModifyCostOptions(o => o.DefaultListSize = 1)
- .AddOpenApi()
- .AddBasicServer();
- services.AddOptions("NamedSchema")
- .PostConfigure(setup => setup.StorageFactory = _ => storage);
- services.AddOpenApi(options => options.AddGraphQLTransformer());
- })
- .Configure(app =>
- {
- app.UseRouting();
- app.UseEndpoints(endpoints =>
- {
- endpoints.MapOpenApi();
- endpoints.MapOpenApiEndpoints();
- });
- });
- using var server = new TestServer(builder);
- var client = server.CreateClient();
+ var webAppBuilder = WebApplication.CreateSlimBuilder();
+ webAppBuilder.WebHost.UseTestServer();
+ webAppBuilder.Services.AddRouting();
+ webAppBuilder.Services
+ .AddGraphQLServer("NamedSchema")
+ .ModifyCostOptions(o => o.DefaultListSize = 1)
+ .AddOpenApi()
+ .AddBasicServer();
+ webAppBuilder.Services
+ .AddOptions("NamedSchema")
+ .PostConfigure(setup => setup.StorageFactory = _ => storage);
+ webAppBuilder.Services.AddOpenApi(options => options.AddGraphQLTransformer());
+ await using var webApp = webAppBuilder.Build();
+ webApp.MapOpenApi();
+ webApp.MapOpenApiEndpoints();
+ webApp.Start();
+ var client = webApp.GetTestClient();
// act
var response = await client.GetAsync("/users", TestContext.Current.CancellationToken);
@@ -116,28 +106,25 @@ query GetUsers @http(method: GET, route: "/users") {
public void MapOpenApiEndpoints_Should_NotResolveSchemaName_When_MultipleNamedSchemasRegistered()
{
// arrange
- var builder = new WebHostBuilder()
- .ConfigureServices(services =>
- {
- services.AddRouting();
-
- foreach (var schemaName in new[] { "alpha", "beta" })
- {
- services.AddGraphQLServer(schemaName)
- .AddOpenApi()
- .AddBasicServer();
- services.AddOptions(schemaName)
- .PostConfigure(setup => setup.StorageFactory = _ => new TestOpenApiDefinitionStorage());
- }
- })
- .Configure(app =>
- {
- app.UseRouting();
- app.UseEndpoints(endpoints => endpoints.MapOpenApiEndpoints());
- });
+ var webAppBuilder = WebApplication.CreateSlimBuilder();
+ webAppBuilder.WebHost.UseTestServer();
+ webAppBuilder.Services.AddRouting();
+
+ foreach (var schemaName in new[] { "alpha", "beta" })
+ {
+ webAppBuilder.Services
+ .AddGraphQLServer(schemaName)
+ .AddOpenApi()
+ .AddBasicServer();
+ webAppBuilder.Services
+ .AddOptions(schemaName)
+ .PostConfigure(setup => setup.StorageFactory = _ => new TestOpenApiDefinitionStorage());
+ }
+
+ var webApp = webAppBuilder.Build();
// act
- var exception = Assert.Throws(() => new TestServer(builder));
+ var exception = Assert.Throws(() => webApp.MapOpenApiEndpoints());
// assert
Assert.Equal(
@@ -150,20 +137,14 @@ public void MapOpenApiEndpoints_Should_NotResolveSchemaName_When_MultipleNamedSc
public void MapOpenApiEndpoints_Should_Throw_When_AddOpenApiNotCalled()
{
// arrange
- var builder = new WebHostBuilder()
- .ConfigureServices(services =>
- {
- services.AddRouting();
- services.AddGraphQLServer();
- })
- .Configure(app =>
- {
- app.UseRouting();
- app.UseEndpoints(endpoints => endpoints.MapOpenApiEndpoints());
- });
+ var webAppBuilder = WebApplication.CreateSlimBuilder();
+ webAppBuilder.WebHost.UseTestServer();
+ webAppBuilder.Services.AddRouting();
+ webAppBuilder.Services.AddGraphQLServer();
+ var webApp = webAppBuilder.Build();
// act
- var exception = Assert.Throws(() => new TestServer(builder));
+ var exception = Assert.Throws(() => webApp.MapOpenApiEndpoints());
// assert
Assert.Equal(
diff --git a/src/HotChocolate/Adapters/test/Adapters.OpenApi.Tests/Endpoints/KestrelHttpEndpointIntegrationTests.cs b/src/HotChocolate/Adapters/test/Adapters.OpenApi.Tests/Endpoints/KestrelHttpEndpointIntegrationTests.cs
index 4334152e140..73181a638f0 100644
--- a/src/HotChocolate/Adapters/test/Adapters.OpenApi.Tests/Endpoints/KestrelHttpEndpointIntegrationTests.cs
+++ b/src/HotChocolate/Adapters/test/Adapters.OpenApi.Tests/Endpoints/KestrelHttpEndpointIntegrationTests.cs
@@ -3,7 +3,6 @@
using System.Text.Json;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
-using Microsoft.AspNetCore.Hosting.Server.Features;
using Microsoft.Extensions.DependencyInjection;
namespace HotChocolate.Adapters.OpenApi;
@@ -51,7 +50,7 @@ public async Task Http_Post_Body_Succeeds_On_Kestrel()
finally
{
await host.StopAsync(cancellationToken);
- host.Dispose();
+ await host.DisposeAsync();
}
}
@@ -79,47 +78,35 @@ public async Task Http_Put_Body_Succeeds_On_Kestrel()
finally
{
await host.StopAsync(cancellationToken);
- host.Dispose();
+ await host.DisposeAsync();
}
}
- private async Task StartKestrelHostAsync(
+ private async Task StartKestrelHostAsync(
IOpenApiDefinitionStorage storage,
CancellationToken cancellationToken)
{
- var host = new WebHostBuilder()
- .UseKestrel()
- .UseUrls("http://127.0.0.1:0")
- .ConfigureServices(services =>
- {
- services.AddRouting();
-
- services.AddGraphQLServer()
- .AddOpenApi()
- .AddOpenApiDefinitionStorage(storage)
- .AddBasicServer();
- })
- .Configure(app =>
- {
- app.UseRouting();
- app.UseEndpoints(endpoints =>
- {
- endpoints.MapOpenApiEndpoints();
- endpoints.MapGraphQL();
- });
- })
- .Build();
+ var builder = WebApplication.CreateSlimBuilder();
+ builder.WebHost.UseKestrel();
+ builder.WebHost.UseUrls("http://127.0.0.1:0");
+ builder.Services.AddRouting();
+ builder.Services
+ .AddGraphQLServer()
+ .AddOpenApi()
+ .AddOpenApiDefinitionStorage(storage)
+ .AddBasicServer();
+
+ var host = builder.Build();
+ host.MapOpenApiEndpoints();
+ host.MapGraphQL();
await host.StartAsync(cancellationToken);
return host;
}
- private static Uri GetBaseAddress(IWebHost host)
+ private static Uri GetBaseAddress(WebApplication host)
{
- var addresses = host.ServerFeatures.Get()?.Addresses
- ?? throw new InvalidOperationException("Kestrel did not expose any server addresses.");
-
- var address = addresses.FirstOrDefault()
+ var address = host.Urls.FirstOrDefault()
?? throw new InvalidOperationException("Kestrel did not bind to any address.");
return new Uri(address);
diff --git a/src/HotChocolate/Adapters/test/Adapters.OpenApi.Tests/OpenApi/OpenApiIntegrationTests.cs b/src/HotChocolate/Adapters/test/Adapters.OpenApi.Tests/OpenApi/OpenApiIntegrationTests.cs
index 064b66faaa1..e28953661be 100644
--- a/src/HotChocolate/Adapters/test/Adapters.OpenApi.Tests/OpenApi/OpenApiIntegrationTests.cs
+++ b/src/HotChocolate/Adapters/test/Adapters.OpenApi.Tests/OpenApi/OpenApiIntegrationTests.cs
@@ -1,7 +1,7 @@
using Microsoft.AspNetCore.Builder;
-using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
namespace HotChocolate.Adapters.OpenApi;
@@ -30,23 +30,19 @@ query GetUsers @http(method: GET, route: "/users") {
}
}
""");
- var builder = new WebHostBuilder()
- .ConfigureServices(services =>
- {
- services.AddRouting();
- services.AddGraphQLServer("NamedSchema")
- .AddOpenApi()
- .AddOpenApiDefinitionStorage(storage)
- .AddBasicServer();
- services.AddOpenApi(options => options.AddGraphQLTransformer());
- })
- .Configure(app =>
- {
- app.UseRouting();
- app.UseEndpoints(endpoints => endpoints.MapOpenApi());
- });
- using var server = new TestServer(builder);
- var client = server.CreateClient();
+ var webAppBuilder = WebApplication.CreateSlimBuilder();
+ webAppBuilder.WebHost.UseTestServer();
+ webAppBuilder.Services.AddRouting();
+ webAppBuilder.Services
+ .AddGraphQLServer("NamedSchema")
+ .AddOpenApi()
+ .AddOpenApiDefinitionStorage(storage)
+ .AddBasicServer();
+ webAppBuilder.Services.AddOpenApi(options => options.AddGraphQLTransformer());
+ await using var webApp = webAppBuilder.Build();
+ webApp.MapOpenApi();
+ webApp.Start();
+ var client = webApp.GetTestClient();
// act
var document = await GetOpenApiDocumentAsync(client);
diff --git a/src/HotChocolate/Adapters/test/Adapters.OpenApi.Tests/OpenApiTestBase.cs b/src/HotChocolate/Adapters/test/Adapters.OpenApi.Tests/OpenApiTestBase.cs
index 0c2093c52b1..54b0144ccfa 100644
--- a/src/HotChocolate/Adapters/test/Adapters.OpenApi.Tests/OpenApiTestBase.cs
+++ b/src/HotChocolate/Adapters/test/Adapters.OpenApi.Tests/OpenApiTestBase.cs
@@ -165,11 +165,7 @@ public ValueTask InitializeAsync()
protected virtual ValueTask InitializeAsync(TestServerSession serverSession) => ValueTask.CompletedTask;
- public ValueTask DisposeAsync()
- {
- _testServerSession.Dispose();
- return ValueTask.CompletedTask;
- }
+ public ValueTask DisposeAsync() => _testServerSession.DisposeAsync();
protected abstract void ConfigureStorage(
IServiceCollection services,
diff --git a/src/HotChocolate/Adapters/test/Adapters.OpenApi.Tests/TestServerSession.cs b/src/HotChocolate/Adapters/test/Adapters.OpenApi.Tests/TestServerSession.cs
index 2269d1039fb..c4e410094d1 100644
--- a/src/HotChocolate/Adapters/test/Adapters.OpenApi.Tests/TestServerSession.cs
+++ b/src/HotChocolate/Adapters/test/Adapters.OpenApi.Tests/TestServerSession.cs
@@ -1,37 +1,44 @@
using System.Threading.Channels;
using Microsoft.AspNetCore.Builder;
-using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
namespace HotChocolate.Adapters.OpenApi;
-public sealed class TestServerSession : IDisposable
+public sealed class TestServerSession : IAsyncDisposable
{
- private readonly Channel _cleanupPipeline = Channel.CreateUnbounded();
+ private readonly Channel _cleanupPipeline = Channel.CreateUnbounded();
private bool _disposed;
public TestServer CreateServer(
Action configureServices,
Action configureApplication)
{
- var builder = new WebHostBuilder()
- .Configure(configureApplication)
- .ConfigureServices(configureServices);
+ var options = new WebApplicationOptions
+ {
+ ApplicationName = typeof(TestServerSession).Assembly.GetName().Name!
+ };
+ var builder = WebApplication.CreateEmptyBuilder(options);
+ builder.WebHost.UseTestServer();
+ configureServices(builder.Services);
+
+ var app = builder.Build();
+ configureApplication(app);
- var server = new TestServer(builder);
+ app.Start();
- if (!_cleanupPipeline.Writer.TryWrite(server))
+ if (!_cleanupPipeline.Writer.TryWrite(app))
{
- server.Dispose();
+ ((IHost)app).Dispose();
throw new InvalidOperationException(
"Failed to add test server to cleanup pipeline.");
}
- return server;
+ return app.GetTestServer();
}
- public void Dispose()
+ public async ValueTask DisposeAsync()
{
if (_disposed)
{
@@ -42,9 +49,10 @@ public void Dispose()
_cleanupPipeline.Writer.TryComplete();
- while (_cleanupPipeline.Reader.TryRead(out var server))
+ while (_cleanupPipeline.Reader.TryRead(out var app))
{
- server.Dispose();
+ await app.StopAsync();
+ await app.DisposeAsync();
}
}
}
diff --git a/src/HotChocolate/AspNetCore/test/AspNetCore.Authorization.Tests/AuthorizationPolicyProviderTests.cs b/src/HotChocolate/AspNetCore/test/AspNetCore.Authorization.Tests/AuthorizationPolicyProviderTests.cs
index ce99e26376f..64d24f04c66 100644
--- a/src/HotChocolate/AspNetCore/test/AspNetCore.Authorization.Tests/AuthorizationPolicyProviderTests.cs
+++ b/src/HotChocolate/AspNetCore/test/AspNetCore.Authorization.Tests/AuthorizationPolicyProviderTests.cs
@@ -130,7 +130,7 @@ public class CustomAuthorizationPolicyProvider(bool allowsCaching) : IAuthorizat
public Task GetDefaultPolicyAsync() => throw new NotImplementedException();
- public Task GetFallbackPolicyAsync() => throw new NotImplementedException();
+ public Task GetFallbackPolicyAsync() => Task.FromResult(null);
public virtual bool AllowsCachingPolicies => allowsCaching;
}
diff --git a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests.Utilities/ServerTestBase.cs b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests.Utilities/ServerTestBase.cs
index 82b50306dff..ce803f28814 100644
--- a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests.Utilities/ServerTestBase.cs
+++ b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests.Utilities/ServerTestBase.cs
@@ -169,12 +169,7 @@ protected virtual TestServer CreateServer(
///
/// Disposes the servers the current test created.
///
- public virtual ValueTask DisposeAsync()
- {
- ServerFactory.DisposeServers();
-
- return ValueTask.CompletedTask;
- }
+ public virtual ValueTask DisposeAsync() => ServerFactory.DisposeServersAsync();
[DirectiveType(DirectiveLocation.Subscription)]
public class Foo
diff --git a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests.Utilities/Subscriptions/Apollo/SubscriptionTestBase.cs b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests.Utilities/Subscriptions/Apollo/SubscriptionTestBase.cs
index 9b63ed51451..ce447d08430 100644
--- a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests.Utilities/Subscriptions/Apollo/SubscriptionTestBase.cs
+++ b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests.Utilities/Subscriptions/Apollo/SubscriptionTestBase.cs
@@ -19,7 +19,7 @@ public SubscriptionTestBase(TestServerFactory serverFactory)
WebSocket webSocket,
string type,
CancellationToken cancellationToken)
- => WaitForMessage(webSocket, type, TimeSpan.FromMilliseconds(500), cancellationToken);
+ => WaitForMessage(webSocket, type, TimeSpan.FromSeconds(5), cancellationToken);
protected async Task WaitForMessage(
WebSocket webSocket,
@@ -110,39 +110,28 @@ protected static WebSocketClient CreateWebSocketClient(TestServer testServer)
return client;
}
- protected static async Task TryTest(Func action)
+ protected static async Task RunTest(Func action)
{
- // we will try four times ....
- using var cts = new CancellationTokenSource(Debugger.IsAttached ? 600_000_000 : 60_000);
- var ct = cts.Token;
- var count = 0;
- var wait = 50;
+ using var cts = new CancellationTokenSource(Debugger.IsAttached ? 600_000_000 : 30_000);
+ await action(cts.Token);
+ }
+
+ protected static async Task WaitForServerClose(
+ WebSocket webSocket,
+ CancellationToken cancellationToken)
+ {
+ var buffer = new byte[256];
- while (true)
+ while (webSocket.State is WebSocketState.Open or WebSocketState.CloseSent)
{
- ct.ThrowIfCancellationRequested();
+ var result = await webSocket.ReceiveAsync(
+ new ArraySegment(buffer),
+ cancellationToken);
- if (count < 3)
- {
- try
- {
- await action(ct).ConfigureAwait(false);
- break;
- }
- catch
- {
- // try again
- }
- }
- else
+ if (result.MessageType == WebSocketMessageType.Close)
{
- await action(ct).ConfigureAwait(false);
- break;
+ return;
}
-
- await Task.Delay(wait, ct).ConfigureAwait(false);
- wait *= 2;
- count++;
}
}
}
diff --git a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests.Utilities/Subscriptions/GraphQLOverWebSocket/SubscriptionTestBase.cs b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests.Utilities/Subscriptions/GraphQLOverWebSocket/SubscriptionTestBase.cs
index 0bc70614506..84ac6f81819 100644
--- a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests.Utilities/Subscriptions/GraphQLOverWebSocket/SubscriptionTestBase.cs
+++ b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests.Utilities/Subscriptions/GraphQLOverWebSocket/SubscriptionTestBase.cs
@@ -21,7 +21,7 @@ public class SubscriptionTestBase(TestServerFactory serverFactory)
WebSocket webSocket,
string type,
CancellationToken cancellationToken)
- => WaitForMessage(webSocket, type, TimeSpan.FromSeconds(1), cancellationToken);
+ => WaitForMessage(webSocket, type, TimeSpan.FromSeconds(5), cancellationToken);
protected async Task WaitForMessage(
WebSocket webSocket,
@@ -159,39 +159,28 @@ protected static WebSocketClient CreateWebSocketClient(TestServer testServer)
return client;
}
- protected static async Task TryTest(Func action)
+ protected static async Task RunTest(Func action)
{
- // we will try four times ...
- using var cts = new CancellationTokenSource(Debugger.IsAttached ? 600_000_000 : 15_000);
- var ct = cts.Token;
- var count = 0;
- var wait = 50;
+ using var cts = new CancellationTokenSource(Debugger.IsAttached ? 600_000_000 : 30_000);
+ await action(cts.Token);
+ }
+
+ protected static async Task WaitForServerClose(
+ WebSocket webSocket,
+ CancellationToken cancellationToken)
+ {
+ var buffer = new byte[256];
- while (true)
+ while (webSocket.State is WebSocketState.Open or WebSocketState.CloseSent)
{
- ct.ThrowIfCancellationRequested();
+ var result = await webSocket.ReceiveAsync(
+ new ArraySegment(buffer),
+ cancellationToken);
- if (count < 3)
- {
- try
- {
- await action(ct).ConfigureAwait(false);
- break;
- }
- catch
- {
- // try again
- }
- }
- else
+ if (result.MessageType == WebSocketMessageType.Close)
{
- await action(ct).ConfigureAwait(false);
- break;
+ return;
}
-
- await Task.Delay(wait, ct).ConfigureAwait(false);
- wait *= 2;
- count++;
}
}
}
diff --git a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests.Utilities/TestServerFactory.cs b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests.Utilities/TestServerFactory.cs
index 794ccb00d90..8dbd5a24a63 100644
--- a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests.Utilities/TestServerFactory.cs
+++ b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests.Utilities/TestServerFactory.cs
@@ -1,41 +1,42 @@
using Microsoft.AspNetCore.Builder;
-using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
namespace HotChocolate.AspNetCore.Tests.Utilities;
-public class TestServerFactory : IDisposable
+public class TestServerFactory : IAsyncDisposable
{
- private readonly List _instances = [];
+ private readonly List _instances = [];
public TestServer Create(
Action configureServices,
Action configureApplication)
{
- var builder = new WebHostBuilder()
- .Configure(configureApplication)
- .ConfigureServices(services =>
- {
- services.AddHttpContextAccessor();
- configureServices(services);
- });
-
- var server = new TestServer(builder);
- _instances.Add(server);
- return server;
+ var builder = WebApplication.CreateEmptyBuilder(new WebApplicationOptions());
+ builder.WebHost.UseTestServer();
+ builder.Services.AddHttpContextAccessor();
+ configureServices(builder.Services);
+
+ var app = builder.Build();
+ configureApplication(app);
+
+ app.Start();
+ _instances.Add(app);
+ return app.GetTestServer();
}
- public void Dispose() => DisposeServers();
+ public ValueTask DisposeAsync() => DisposeServersAsync();
///
- /// Disposes and releases every server this factory has created so far.
+ /// Stops, disposes, and releases every server this factory has created so far.
///
- public void DisposeServers()
+ public async ValueTask DisposeServersAsync()
{
- foreach (var testServer in _instances)
+ foreach (var app in _instances)
{
- testServer.Dispose();
+ await app.StopAsync();
+ await app.DisposeAsync();
}
_instances.Clear();
diff --git a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/GraphQLOverHttpSpecTests.cs b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/GraphQLOverHttpSpecTests.cs
index d977f35c6fe..9d1c84ce7b1 100644
--- a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/GraphQLOverHttpSpecTests.cs
+++ b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/GraphQLOverHttpSpecTests.cs
@@ -448,7 +448,7 @@ public async Task EventStream_When_Accept_Is_All()
// arrange
var server = CreateStarWarsServer();
var client = server.CreateClient();
- client.Timeout = TimeSpan.FromSeconds(30);
+ client.Timeout = TimeSpan.FromSeconds(60);
// act
using var request = new HttpRequestMessage(HttpMethod.Post, s_url);
@@ -459,39 +459,25 @@ public async Task EventStream_When_Accept_Is_All()
});
request.Headers.Add("Accept", "*/*");
- using var response = await client.SendAsync(
+ using var httpResponse = await client.SendAsync(
request,
ResponseHeadersRead,
TestContext.Current.CancellationToken);
+ using var response = new GraphQLHttpResponse(httpResponse);
// assert
- Snapshot
- .Create()
- .Add(response)
- .MatchInline(
- """
- Headers:
- Vary: Accept
- Cache-Control: no-cache
- Content-Type: text/event-stream; charset=utf-8
- -------------------------->
- Status Code: OK
- -------------------------->
- event: next
- data: {"data":{"delay":"next"}}
-
- :
-
- event: next
- data: {"data":{"delay":"next"}}
-
- :
+ Assert.Equal(OK, response.StatusCode);
+ Assert.Equal("text/event-stream", httpResponse.Content.Headers.ContentType?.MediaType);
- event: complete
- data:
+ var results = new List();
+ await foreach (var result in response.ReadAsResultStreamAsync())
+ {
+ results.Add(result.Data.ToString());
+ }
- """);
+ Assert.Equal(2, results.Count);
+ Assert.All(results, r => Assert.Equal("{\"delay\":\"next\"}", r));
}
[Fact]
@@ -500,7 +486,7 @@ public async Task EventStream_When_Accept_Is_All_And_Subscription_Directive()
// arrange
var server = CreateStarWarsServer();
var client = server.CreateClient();
- client.Timeout = TimeSpan.FromSeconds(30);
+ client.Timeout = TimeSpan.FromSeconds(60);
// act
using var request = new HttpRequestMessage(HttpMethod.Post, s_url);
@@ -511,39 +497,25 @@ public async Task EventStream_When_Accept_Is_All_And_Subscription_Directive()
});
request.Headers.Add("Accept", "*/*");
- using var response = await client.SendAsync(
+ using var httpResponse = await client.SendAsync(
request,
ResponseHeadersRead,
TestContext.Current.CancellationToken);
+ using var response = new GraphQLHttpResponse(httpResponse);
// assert
- Snapshot
- .Create()
- .Add(response)
- .MatchInline(
- """
- Headers:
- Vary: Accept
- Cache-Control: no-cache
- Content-Type: text/event-stream; charset=utf-8
- -------------------------->
- Status Code: OK
- -------------------------->
- event: next
- data: {"data":{"delay":"next"}}
-
- :
-
- event: next
- data: {"data":{"delay":"next"}}
-
- :
+ Assert.Equal(OK, response.StatusCode);
+ Assert.Equal("text/event-stream", httpResponse.Content.Headers.ContentType?.MediaType);
- event: complete
- data:
+ var results = new List();
+ await foreach (var result in response.ReadAsResultStreamAsync())
+ {
+ results.Add(result.Data.ToString());
+ }
- """);
+ Assert.Equal(2, results.Count);
+ Assert.All(results, r => Assert.Equal("{\"delay\":\"next\"}", r));
}
[Fact]
diff --git a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/Subscriptions/Apollo/WebSocketProtocolTests.cs b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/Subscriptions/Apollo/WebSocketProtocolTests.cs
index 21c6b50653f..61fe537cb46 100644
--- a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/Subscriptions/Apollo/WebSocketProtocolTests.cs
+++ b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/Subscriptions/Apollo/WebSocketProtocolTests.cs
@@ -19,7 +19,7 @@ public class WebSocketProtocolTests(TestServerFactory serverFactory)
{
[Fact]
public Task Send_Connect_AcceptAndKeepAlive()
- => TryTest(async ct =>
+ => RunTest(async ct =>
{
// arrange
using var testServer = CreateStarWarsServer();
@@ -37,7 +37,7 @@ public Task Send_Connect_AcceptAndKeepAlive()
[Fact]
public Task Send_Connect_To_Many_Init_Messages()
- => TryTest(async ct =>
+ => RunTest(async ct =>
{
// arrange
using var testServer = CreateStarWarsServer();
@@ -51,14 +51,14 @@ public Task Send_Connect_To_Many_Init_Messages()
await webSocket.SendConnectionInitializeAsync(ct);
// assert
- await webSocket.ReceiveServerMessageAsync(ct);
+ await WaitForServerClose(webSocket, ct);
Assert.True(webSocket.CloseStatus.HasValue);
Assert.Equal(WebSocketCloseStatus.ProtocolError, webSocket.CloseStatus.Value);
});
[Fact]
public Task No_ConnectionInit_Timeout()
- => TryTest(async ct =>
+ => RunTest(async ct =>
{
// arrange
using var testServer = CreateStarWarsServer(
@@ -75,14 +75,14 @@ public Task No_ConnectionInit_Timeout()
using var webSocket = await client.ConnectAsync(SubscriptionUri, ct);
// assert
- await webSocket.ReceiveServerMessageAsync(ct);
+ await WaitForServerClose(webSocket, ct);
Assert.True(webSocket.CloseStatus.HasValue, "Connection is closed.");
Assert.Equal(WebSocketCloseStatus.ProtocolError, webSocket.CloseStatus.Value);
});
[Fact]
public Task Send_Connect_With_Auth_Accept()
- => TryTest(async ct =>
+ => RunTest(async ct =>
{
// arrange
var interceptor = new AuthInterceptor();
@@ -104,7 +104,7 @@ public Task Send_Connect_With_Auth_Accept()
[Fact]
public Task Send_Connect_With_Auth_Reject()
- => TryTest(async ct =>
+ => RunTest(async ct =>
{
// arrange
var interceptor = new AuthInterceptor();
@@ -120,14 +120,14 @@ public Task Send_Connect_With_Auth_Reject()
// assert
await WaitForMessage(webSocket, "connection_error", ct);
- await webSocket.ReceiveServerMessageAsync(ct);
+ await WaitForServerClose(webSocket, ct);
Assert.True(webSocket.CloseStatus.HasValue, "Connection is closed.");
Assert.Equal(WebSocketCloseStatus.NormalClosure, webSocket.CloseStatus.Value);
});
[Fact]
public Task Send_Connect_AcceptAndKeepAlive_Explicit_Route()
- => TryTest(async ct =>
+ => RunTest(async ct =>
{
// arrange
using var testServer = CreateServer(b => b.MapGraphQLWebSocket());
@@ -147,7 +147,7 @@ public Task Send_Connect_AcceptAndKeepAlive_Explicit_Route()
[Fact]
public Task Send_Connect_AcceptAndKeepAlive_Explicit_Route_Explicit_Path()
- => TryTest(async ct =>
+ => RunTest(async ct =>
{
// arrange
using var testServer = CreateServer(b => b.MapGraphQLWebSocket("/foo/bar"));
@@ -167,7 +167,7 @@ public Task Send_Connect_AcceptAndKeepAlive_Explicit_Route_Explicit_Path()
[Fact]
public Task Send_Terminate()
- => TryTest(async ct =>
+ => RunTest(async ct =>
{
// arrange
using var testServer = CreateStarWarsServer();
@@ -186,7 +186,7 @@ public Task Send_Terminate()
[Fact]
public Task Connect_With_Invalid_Protocol()
- => TryTest(async ct =>
+ => RunTest(async ct =>
{
// arrange
using var testServer = CreateStarWarsServer();
@@ -196,10 +196,9 @@ public Task Connect_With_Invalid_Protocol()
// act
var socket = await client.ConnectAsync(SubscriptionUri, ct);
- var buffer = new byte[1024];
- await socket.ReceiveAsync(buffer, ct);
// assert
+ await WaitForServerClose(socket, ct);
Assert.True(socket.CloseStatus.HasValue);
Assert.Equal(WebSocketCloseStatus.ProtocolError, socket.CloseStatus.Value);
});
@@ -210,7 +209,7 @@ public Task Send_Start_ReceiveDataOnMutation()
{
var snapshot = new Snapshot();
- return TryTest(async ct =>
+ return RunTest(async ct =>
{
// arrange
using var testServer = CreateStarWarsServer();
@@ -250,7 +249,7 @@ await testServer.SendPostRequestAsync(
[Fact]
public Task Send_Start_Id_Not_Unique()
- => TryTest(async ct =>
+ => RunTest(async ct =>
{
// arrange
using var testServer = CreateStarWarsServer();
@@ -268,14 +267,14 @@ public Task Send_Start_Id_Not_Unique()
await webSocket.SendSubscriptionStartAsync(subscriptionId, request);
// assert
- await webSocket.ReceiveServerMessageAsync(ct);
+ await WaitForServerClose(webSocket, ct);
Assert.True(webSocket.CloseStatus.HasValue);
Assert.Equal(WebSocketCloseStatus.InternalServerError, webSocket.CloseStatus.Value);
});
[Fact]
public Task Send_Subscribe_No_Id()
- => TryTest(async ct =>
+ => RunTest(async ct =>
{
// arrange
using var testServer = CreateStarWarsServer();
@@ -287,14 +286,14 @@ public Task Send_Subscribe_No_Id()
await webSocket.SendMessageAsync("{ \"type\": \"subscribe\" }", ct);
// assert
- await webSocket.ReceiveServerMessageAsync(ct);
+ await WaitForServerClose(webSocket, ct);
Assert.True(webSocket.CloseStatus.HasValue);
Assert.Equal(CloseReasons.InvalidMessage, (int)webSocket.CloseStatus.Value);
});
[Fact]
public Task Send_Subscribe_Empty_Id()
- => TryTest(async ct =>
+ => RunTest(async ct =>
{
// arrange
using var testServer = CreateStarWarsServer();
@@ -306,7 +305,7 @@ public Task Send_Subscribe_Empty_Id()
await webSocket.SendMessageAsync("{ \"type\": \"subscribe\", \"id\": \"\" }", ct);
// assert
- await webSocket.ReceiveServerMessageAsync(ct);
+ await WaitForServerClose(webSocket, ct);
Assert.True(webSocket.CloseStatus.HasValue);
Assert.Equal(CloseReasons.InvalidMessage, (int)webSocket.CloseStatus.Value);
});
@@ -316,7 +315,7 @@ public Task Send_Subscribe_SyntaxError()
{
var snapshot = new Snapshot();
- return TryTest(
+ return RunTest(
async ct =>
{
// arrange
@@ -348,7 +347,7 @@ await webSocket.SendMessageAsync(
[Fact]
public Task Send_Subscribe_SyntaxError_No_Id()
- => TryTest(
+ => RunTest(
async ct =>
{
// arrange
@@ -372,17 +371,21 @@ await webSocket.SendMessageAsync(
ct);
// assert
- await webSocket.ReceiveServerMessageAsync(ct);
+ await WaitForServerClose(webSocket, ct);
Assert.True(webSocket.CloseStatus.HasValue);
Assert.Equal(CloseReasons.InvalidMessage, (int)webSocket.CloseStatus.Value);
});
[Fact]
public Task Send_Start_Stop()
- => TryTest(async ct =>
+ => RunTest(async ct =>
{
// arrange
- using var testServer = CreateStarWarsServer();
+ var diagnostics = new SubscriptionTestDiagnostics();
+ using var testServer = CreateStarWarsServer(
+ configureServices: s => s
+ .AddGraphQL()
+ .AddDiagnosticEventListener(_ => diagnostics));
var client = CreateWebSocketClient(testServer);
var webSocket = await ConnectToServerAsync(client, ct);
@@ -394,6 +397,7 @@ public Task Send_Start_Stop()
const string subscriptionId = "abc";
await webSocket.SendSubscriptionStartAsync(subscriptionId, request);
+ await diagnostics.WaitForSubscribedAsync(ct);
await testServer.SendPostRequestAsync(new ClientQueryRequest
{
@@ -417,6 +421,7 @@ await testServer.SendPostRequestAsync(new ClientQueryRequest
// act
await webSocket.SendSubscriptionStopAsync(subscriptionId, ct);
+ await diagnostics.WaitForUnsubscribeAsync(ct);
await testServer.SendPostRequestAsync(new ClientQueryRequest
{
@@ -446,7 +451,7 @@ public Task Send_Start_ValidationError()
{
var snapshot = new Snapshot();
- return TryTest(async ct =>
+ return RunTest(async ct =>
{
// arrange
using var testServer = CreateStarWarsServer();
@@ -470,7 +475,7 @@ public Task Send_Start_ValidationError()
[Fact]
public Task Send_Invalid_Message_String()
- => TryTest(async ct =>
+ => RunTest(async ct =>
{
// arrange
using var testServer = CreateStarWarsServer();
@@ -481,14 +486,14 @@ public Task Send_Invalid_Message_String()
await webSocket.SendMessageAsync("hello", ct);
// assert
- await webSocket.ReceiveServerMessageAsync(ct);
+ await WaitForServerClose(webSocket, ct);
Assert.True(webSocket.CloseStatus.HasValue, "Connection is closed.");
Assert.Equal(WebSocketCloseStatus.InternalServerError, webSocket.CloseStatus.Value);
});
[Fact]
public Task Send_Invalid_Message_No_Type()
- => TryTest(async ct =>
+ => RunTest(async ct =>
{
// arrange
using var testServer = CreateStarWarsServer();
@@ -499,14 +504,14 @@ public Task Send_Invalid_Message_No_Type()
await webSocket.SendMessageAsync("{ }", ct);
// assert
- await webSocket.ReceiveServerMessageAsync(ct);
+ await WaitForServerClose(webSocket, ct);
Assert.True(webSocket.CloseStatus.HasValue, "Connection is closed.");
Assert.Equal(CloseReasons.InvalidMessage, (int)webSocket.CloseStatus.Value);
});
[Fact]
public Task Send_Invalid_Message_Invalid_Type()
- => TryTest(async ct =>
+ => RunTest(async ct =>
{
// arrange
using var testServer = CreateStarWarsServer();
@@ -517,14 +522,14 @@ public Task Send_Invalid_Message_Invalid_Type()
await webSocket.SendMessageAsync("{ \"type\": \"abc\" }", ct);
// assert
- await webSocket.ReceiveServerMessageAsync(ct);
+ await WaitForServerClose(webSocket, ct);
Assert.True(webSocket.CloseStatus.HasValue, "Connection is closed.");
Assert.Equal(CloseReasons.InvalidMessage, (int)webSocket.CloseStatus.Value);
});
[Fact]
public Task Send_Invalid_Message_Not_An_Object()
- => TryTest(async ct =>
+ => RunTest(async ct =>
{
// arrange
using var testServer = CreateStarWarsServer();
@@ -535,7 +540,7 @@ public Task Send_Invalid_Message_Not_An_Object()
await webSocket.SendMessageAsync("[]", ct);
// assert
- await webSocket.ReceiveServerMessageAsync(ct);
+ await WaitForServerClose(webSocket, ct);
Assert.True(webSocket.CloseStatus.HasValue, "Connection is closed.");
Assert.Equal(CloseReasons.InvalidMessage, (int)webSocket.CloseStatus.Value);
});
@@ -543,7 +548,7 @@ public Task Send_Invalid_Message_Not_An_Object()
// TODO : FIX Flaky Test
[Fact(Skip = "Flaky")]
public Task Send_Start_ReceiveDataOnMutation_StripNull() =>
- TryTest(
+ RunTest(
async ct =>
{
// arrange
@@ -598,7 +603,7 @@ await testServer.SendPostRequestAsync(
[Fact]
public Task Connection_Reject_With_Long_Message_Should_Close_Cleanly()
- => TryTest(async ct =>
+ => RunTest(async ct =>
{
// arrange
// a rejection message longer than the 123 UTF-8 byte close-frame limit.
@@ -620,14 +625,14 @@ public Task Connection_Reject_With_Long_Message_Should_Close_Cleanly()
Assert.Equal(
longMessage,
error.RootElement.GetProperty("payload").GetProperty("message").GetString());
- await webSocket.ReceiveServerMessageAsync(ct);
+ await WaitForServerClose(webSocket, ct);
Assert.True(webSocket.CloseStatus.HasValue, "Connection is closed.");
Assert.Equal(WebSocketCloseStatus.NormalClosure, webSocket.CloseStatus.Value);
});
[Fact]
public Task Connection_Terminate_Should_Invoke_OnClose_Once()
- => TryTest(async ct =>
+ => RunTest(async ct =>
{
// arrange
var interceptor = new OnCloseCountingInterceptor();
@@ -651,7 +656,7 @@ public Task Connection_Terminate_Should_Invoke_OnClose_Once()
[Fact]
public Task Client_KeepAlive_Should_Not_Close_Connection()
- => TryTest(async ct =>
+ => RunTest(async ct =>
{
// arrange
using var testServer = CreateStarWarsServer();
diff --git a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/Subscriptions/GraphQLOverWebSocket/WebSocketProtocolTests.cs b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/Subscriptions/GraphQLOverWebSocket/WebSocketProtocolTests.cs
index 8a4df40ce2e..947f42024b8 100644
--- a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/Subscriptions/GraphQLOverWebSocket/WebSocketProtocolTests.cs
+++ b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/Subscriptions/GraphQLOverWebSocket/WebSocketProtocolTests.cs
@@ -11,7 +11,6 @@
using HotChocolate.Execution;
using HotChocolate.Language;
using HotChocolate.PersistedOperations;
-using HotChocolate.Subscriptions.Diagnostics;
using HotChocolate.Text.Json;
using HotChocolate.Transport.Formatters;
using HotChocolate.Transport.Sockets.Client;
@@ -27,7 +26,7 @@ public class WebSocketProtocolTests(TestServerFactory serverFactory, ITestOutput
{
[Fact]
public Task Send_Connect_Accept()
- => TryTest(
+ => RunTest(
async ct =>
{
// arrange
@@ -46,7 +45,7 @@ public Task Send_Connect_Accept()
[Fact]
public Task Send_Multiple_Connect_Messages_Close_Connection()
- => TryTest(
+ => RunTest(
async ct =>
{
// arrange
@@ -61,14 +60,14 @@ public Task Send_Multiple_Connect_Messages_Close_Connection()
await webSocket.SendConnectionInitAsync(ct);
// assert
- await webSocket.ReceiveServerMessageAsync(ct);
+ await WaitForServerClose(webSocket, ct);
Assert.True(webSocket.CloseStatus.HasValue);
Assert.Equal(CloseReasons.TooManyInitAttempts, (int)webSocket.CloseStatus.Value);
});
[Fact]
public Task Send_Connect_Accept_Ping()
- => TryTest(
+ => RunTest(
async ct =>
{
// arrange
@@ -100,7 +99,7 @@ public Task Send_Connect_Accept_Ping()
[Fact]
public Task No_ConnectionInit_Timeout()
- => TryTest(
+ => RunTest(
async ct =>
{
// arrange
@@ -119,7 +118,7 @@ public Task No_ConnectionInit_Timeout()
using var webSocket = await client.ConnectAsync(SubscriptionUri, ct);
// assert
- await webSocket.ReceiveServerMessageAsync(ct);
+ await WaitForServerClose(webSocket, ct);
Assert.True(webSocket.CloseStatus.HasValue, "Connection is closed.");
Assert.Equal(
CloseReasons.ConnectionInitWaitTimeout,
@@ -128,7 +127,7 @@ public Task No_ConnectionInit_Timeout()
[Fact]
public Task Send_Connect_With_Auth_Accept()
- => TryTest(
+ => RunTest(
async ct =>
{
// arrange
@@ -151,7 +150,7 @@ public Task Send_Connect_With_Auth_Accept()
[Fact]
public Task Send_Connect_With_Auth_Reject()
- => TryTest(
+ => RunTest(
async ct =>
{
// arrange
@@ -167,14 +166,14 @@ public Task Send_Connect_With_Auth_Reject()
await webSocket.SendConnectionInitAsync(ct);
// assert
- await webSocket.ReceiveServerMessageAsync(ct);
+ await WaitForServerClose(webSocket, ct);
Assert.True(webSocket.CloseStatus.HasValue, "Connection is closed.");
Assert.Equal(CloseReasons.Forbidden, (int)webSocket.CloseStatus.Value);
});
[Fact]
public Task Connection_Rejected_Should_Close_With_Forbidden()
- => TryTest(
+ => RunTest(
async ct =>
{
// arrange
@@ -190,7 +189,7 @@ public Task Connection_Rejected_Should_Close_With_Forbidden()
await webSocket.SendConnectionInitAsync(ct);
// assert
- await webSocket.ReceiveServerMessageAsync(ct);
+ await WaitForServerClose(webSocket, ct);
Assert.True(webSocket.CloseStatus.HasValue, "Connection is closed.");
Assert.Equal(CloseReasons.Forbidden, (int)webSocket.CloseStatus.Value);
Assert.Equal("You shall not pass.", webSocket.CloseStatusDescription);
@@ -198,7 +197,7 @@ public Task Connection_Rejected_Should_Close_With_Forbidden()
[Fact]
public Task Send_Connect_Accept_Explicit_Route()
- => TryTest(
+ => RunTest(
async ct =>
{
// arrange
@@ -219,7 +218,7 @@ public Task Send_Connect_Accept_Explicit_Route()
[Fact]
public Task Send_Connect_Accept_Explicit_Route_Explicit_Path()
- => TryTest(
+ => RunTest(
async ct =>
{
// arrange
@@ -240,7 +239,7 @@ public Task Send_Connect_Accept_Explicit_Route_Explicit_Path()
[Fact]
public Task Connect_With_Invalid_Protocol()
- => TryTest(
+ => RunTest(
async ct =>
{
// arrange
@@ -252,7 +251,7 @@ public Task Connect_With_Invalid_Protocol()
using var socket = await client.ConnectAsync(SubscriptionUri, ct);
// assert
- await socket.ReceiveServerMessageAsync(ct);
+ await WaitForServerClose(socket, ct);
Assert.True(socket.CloseStatus.HasValue);
Assert.Equal(ProtocolError, socket.CloseStatus.Value);
});
@@ -262,7 +261,7 @@ public Task Subscribe_ReceiveDataOnMutation()
{
var snapshot = new Snapshot();
- return TryTest(
+ return RunTest(
async ct =>
{
// arrange
@@ -314,7 +313,7 @@ await testServer.SendPostRequestAsync(
[Fact]
public Task Subscribe_With_PersistedQuery_Extension_Only_Works()
- => TryTest(
+ => RunTest(
async ct =>
{
// arrange
@@ -381,7 +380,7 @@ await testServer.SendPostRequestAsync(
[Fact]
public Task Subscribe_Id_Not_Unique()
{
- return TryTest(
+ return RunTest(
async ct =>
{
// arrange
@@ -398,7 +397,7 @@ public Task Subscribe_Id_Not_Unique()
await webSocket.SendSubscribeAsync(subscriptionId, payload, ct);
// assert
- await webSocket.ReceiveServerMessageAsync(ct);
+ await WaitForServerClose(webSocket, ct);
Assert.True(webSocket.CloseStatus.HasValue);
Assert.Equal(CloseReasons.SubscriberNotUnique, (int)webSocket.CloseStatus.Value);
});
@@ -406,7 +405,7 @@ public Task Subscribe_Id_Not_Unique()
[Fact]
public Task Send_Subscribe_No_Auth_Close()
- => TryTest(
+ => RunTest(
async ct =>
{
// arrange
@@ -421,14 +420,14 @@ public Task Send_Subscribe_No_Auth_Close()
await webSocket.SendSubscribeAsync(subscriptionId, payload, ct);
// assert
- await webSocket.ReceiveServerMessageAsync(ct);
+ await WaitForServerClose(webSocket, ct);
Assert.True(webSocket.CloseStatus.HasValue);
Assert.Equal(CloseReasons.Unauthorized, (int)webSocket.CloseStatus.Value);
});
[Fact]
public Task Send_Subscribe_No_Id()
- => TryTest(
+ => RunTest(
async ct =>
{
// arrange
@@ -441,14 +440,14 @@ public Task Send_Subscribe_No_Id()
await webSocket.SendMessageAsync("{ \"type\": \"subscribe\" }", ct);
// assert
- await webSocket.ReceiveServerMessageAsync(ct);
+ await WaitForServerClose(webSocket, ct);
Assert.True(webSocket.CloseStatus.HasValue);
Assert.Equal(CloseReasons.ProtocolError, (int)webSocket.CloseStatus.Value);
});
[Fact]
public Task Send_Subscribe_Empty_Id()
- => TryTest(
+ => RunTest(
async ct =>
{
// arrange
@@ -461,7 +460,7 @@ public Task Send_Subscribe_Empty_Id()
await webSocket.SendMessageAsync("{ \"type\": \"subscribe\", \"id\": \"\" }", ct);
// assert
- await webSocket.ReceiveServerMessageAsync(ct);
+ await WaitForServerClose(webSocket, ct);
Assert.True(webSocket.CloseStatus.HasValue);
Assert.Equal(CloseReasons.ProtocolError, (int)webSocket.CloseStatus.Value);
});
@@ -469,7 +468,7 @@ public Task Send_Subscribe_Empty_Id()
[Fact]
public async Task Send_Subscribe_Complete()
{
- await TryTest(
+ await RunTest(
async ct =>
{
// arrange
@@ -513,6 +512,7 @@ await testServer.SendPostRequestAsync(
// act
await webSocket.SendCompleteAsync(subscriptionId, ct);
+ await diagnostics.WaitForUnsubscribeAsync(ct);
await testServer.SendPostRequestAsync(
new ClientQueryRequest
@@ -532,7 +532,6 @@ await testServer.SendPostRequestAsync(
// assert
Assert.True(await AssertNoMessage(webSocket, Messages.Next, ct));
- await diagnostics.WaitForUnsubscribeAsync(ct);
await diagnostics.WaitForCloseAsync(ct);
});
}
@@ -540,7 +539,7 @@ await testServer.SendPostRequestAsync(
[Fact]
public async Task Send_Subscribe_Complete_From_Server()
{
- await TryTest(
+ await RunTest(
async ct =>
{
// arrange
@@ -602,7 +601,7 @@ await testServer.SendPostRequestAsync(
[Fact]
public async Task Send_Subscribe_100x_Complete_From_Server()
{
- await TryTest(
+ await RunTest(
async ct =>
{
// arrange
@@ -674,7 +673,7 @@ public Task Send_Subscribe_SyntaxError()
{
var snapshot = new Snapshot();
- return TryTest(
+ return RunTest(
async ct =>
{
// arrange
@@ -701,7 +700,7 @@ public Task Send_Subscribe_ValidationError()
{
var snapshot = new Snapshot();
- return TryTest(
+ return RunTest(
async ct =>
{
// arrange
@@ -725,7 +724,7 @@ public Task Send_Subscribe_ValidationError()
[Fact]
public Task Subscribe_With_Error_Should_Not_Send_Complete_After_Error()
- => TryTest(
+ => RunTest(
async ct =>
{
// arrange
@@ -754,7 +753,7 @@ await AssertNoMessage(webSocket, Messages.Complete, ct),
[Fact]
public Task Connection_Init_Received_In_Time_Should_Not_Timeout_When_OnConnect_Is_Slow()
- => TryTest(
+ => RunTest(
async ct =>
{
// arrange
@@ -794,7 +793,7 @@ public Task Send_Ping()
{
var snapshot = new Snapshot();
- return TryTest(
+ return RunTest(
async ct =>
{
// arrange
@@ -821,7 +820,7 @@ public Task Send_Ping_With_Payload()
{
var snapshot = new Snapshot();
- return TryTest(
+ return RunTest(
async ct =>
{
// arrange
@@ -847,7 +846,7 @@ await webSocket.SendPingAsync(
[Fact]
public Task Send_Pong()
- => TryTest(
+ => RunTest(
async ct =>
{
// arrange
@@ -872,7 +871,7 @@ public Task Send_Pong_With_Payload()
{
var snapshot = new Snapshot();
- return TryTest(
+ return RunTest(
async ct =>
{
// arrange
@@ -898,7 +897,7 @@ await webSocket.SendPongAsync(
[Fact]
public Task Send_Invalid_Message_String()
- => TryTest(
+ => RunTest(
async ct =>
{
// arrange
@@ -910,14 +909,14 @@ public Task Send_Invalid_Message_String()
await webSocket.SendMessageAsync("hello", ct);
// assert
- await webSocket.ReceiveServerMessageAsync(ct);
+ await WaitForServerClose(webSocket, ct);
Assert.True(webSocket.CloseStatus.HasValue, "Connection is closed.");
Assert.Equal(CloseReasons.ProtocolError, (int)webSocket.CloseStatus.Value);
});
[Fact]
public Task Malformed_Message_Should_Close_With_BadRequest()
- => TryTest(
+ => RunTest(
async ct =>
{
// arrange
@@ -929,14 +928,14 @@ public Task Malformed_Message_Should_Close_With_BadRequest()
await webSocket.SendMessageAsync("{ \"type\": \"connection_init\"", ct);
// assert
- await webSocket.ReceiveServerMessageAsync(ct);
+ await WaitForServerClose(webSocket, ct);
Assert.True(webSocket.CloseStatus.HasValue, "Connection is closed.");
Assert.Equal(CloseReasons.ProtocolError, (int)webSocket.CloseStatus.Value);
});
[Fact]
public Task Send_Invalid_Message_No_Type()
- => TryTest(
+ => RunTest(
async ct =>
{
// arrange
@@ -948,14 +947,14 @@ public Task Send_Invalid_Message_No_Type()
await webSocket.SendMessageAsync("{ }", ct);
// assert
- await webSocket.ReceiveServerMessageAsync(ct);
+ await WaitForServerClose(webSocket, ct);
Assert.True(webSocket.CloseStatus.HasValue, "Connection is closed.");
Assert.Equal(CloseReasons.ProtocolError, (int)webSocket.CloseStatus.Value);
});
[Fact]
public Task Send_Invalid_Message_Invalid_Type()
- => TryTest(
+ => RunTest(
async ct =>
{
// arrange
@@ -967,14 +966,14 @@ public Task Send_Invalid_Message_Invalid_Type()
await webSocket.SendMessageAsync("{ \"type\": \"abc\" }", ct);
// assert
- await webSocket.ReceiveServerMessageAsync(ct);
+ await WaitForServerClose(webSocket, ct);
Assert.True(webSocket.CloseStatus.HasValue, "Connection is closed.");
Assert.Equal(CloseReasons.ProtocolError, (int)webSocket.CloseStatus.Value);
});
[Fact]
public Task Send_Invalid_Message_Not_An_Object()
- => TryTest(
+ => RunTest(
async ct =>
{
// arrange
@@ -986,14 +985,14 @@ public Task Send_Invalid_Message_Not_An_Object()
await webSocket.SendMessageAsync("[]", ct);
// assert
- await webSocket.ReceiveServerMessageAsync(ct);
+ await WaitForServerClose(webSocket, ct);
Assert.True(webSocket.CloseStatus.HasValue, "Connection is closed.");
Assert.Equal(CloseReasons.ProtocolError, (int)webSocket.CloseStatus.Value);
});
[Fact]
public Task Client_Close_Should_Receive_Server_Close_Frame()
- => TryTest(
+ => RunTest(
async ct =>
{
// arrange
@@ -1016,7 +1015,7 @@ public Task Client_Close_Should_Receive_Server_Close_Frame()
[Fact]
public Task Subscribe_Cancel()
{
- return TryTest(
+ return RunTest(
async ct =>
{
// arrange
@@ -1051,7 +1050,7 @@ public Task Subscribe_Cancel()
[Fact]
public Task Subscribe_ReceiveDataOnMutation_StripNull()
- => TryTest(
+ => RunTest(
async ct =>
{
// arrange
@@ -1218,109 +1217,4 @@ public override ValueTask OnPongAsync(
return base.OnPongAsync(session, pongMessage, cancellationToken);
}
}
-
- public sealed class SubscriptionTestDiagnostics : SubscriptionDiagnosticEventsListener
- {
- private readonly object _sync = new();
- private readonly List<(int Count, TaskCompletionSource Signal)> _subscribedSignals = [];
- private readonly List<(int Count, TaskCompletionSource Signal)> _unsubscribeSignals = [];
- private readonly List<(int Count, TaskCompletionSource Signal)> _closeSignals = [];
- private int _subscribed;
- private int _unsubscribeCount;
- private int _closeCount;
-
- public int Subscribed => _subscribed;
-
- public bool UnsubscribeInvoked { get; private set; }
-
- public bool CloseInvoked { get; private set; }
-
- public override void SubscribeSuccess(string topicName)
- {
- var subscribed = Interlocked.Increment(ref _subscribed);
- SignalCompleted(_subscribedSignals, subscribed);
- }
-
- public override void Unsubscribe(string topicName, int shard, int subscribers)
- {
- UnsubscribeInvoked = true;
- var unsubscribeCount = Interlocked.Increment(ref _unsubscribeCount);
- SignalCompleted(_unsubscribeSignals, unsubscribeCount);
- }
-
- public override void Close(string topicName)
- {
- CloseInvoked = true;
- var closeCount = Interlocked.Increment(ref _closeCount);
- SignalCompleted(_closeSignals, closeCount);
- }
-
- public Task WaitForSubscribedAsync(CancellationToken cancellationToken)
- => WaitForSubscribedAsync(1, cancellationToken);
-
- public Task WaitForSubscribedAsync(int count, CancellationToken cancellationToken)
- => WaitForSignalAsync(_subscribedSignals, count, _subscribed, cancellationToken);
-
- public Task WaitForUnsubscribeAsync(CancellationToken cancellationToken)
- => WaitForUnsubscribeAsync(1, cancellationToken);
-
- public Task WaitForUnsubscribeAsync(int count, CancellationToken cancellationToken)
- => WaitForSignalAsync(_unsubscribeSignals, count, _unsubscribeCount, cancellationToken);
-
- public Task WaitForCloseAsync(CancellationToken cancellationToken)
- => WaitForCloseAsync(1, cancellationToken);
-
- public Task WaitForCloseAsync(int count, CancellationToken cancellationToken)
- => WaitForSignalAsync(_closeSignals, count, _closeCount, cancellationToken);
-
- private Task WaitForSignalAsync(
- List<(int Count, TaskCompletionSource Signal)> signals,
- int count,
- int currentCount,
- CancellationToken cancellationToken)
- {
- if (currentCount >= count)
- {
- return Task.CompletedTask;
- }
-
- TaskCompletionSource signal;
-
- lock (_sync)
- {
- if (GetCurrentCount(signals) >= count)
- {
- return Task.CompletedTask;
- }
-
- signal = new(TaskCreationOptions.RunContinuationsAsynchronously);
- signals.Add((count, signal));
- }
-
- return signal.Task.WaitAsync(cancellationToken);
- }
-
- private int GetCurrentCount(List<(int Count, TaskCompletionSource Signal)> signals)
- => ReferenceEquals(signals, _subscribedSignals)
- ? _subscribed
- : ReferenceEquals(signals, _unsubscribeSignals)
- ? _unsubscribeCount
- : _closeCount;
-
- private void SignalCompleted(List<(int Count, TaskCompletionSource Signal)> signals, int count)
- {
- TaskCompletionSource[] ready;
-
- lock (_sync)
- {
- ready = [.. signals.Where(t => t.Count <= count).Select(t => t.Signal)];
- signals.RemoveAll(t => t.Count <= count);
- }
-
- foreach (var signal in ready)
- {
- signal.TrySetResult();
- }
- }
- }
}
diff --git a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/Subscriptions/SubscriptionTestDiagnostics.cs b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/Subscriptions/SubscriptionTestDiagnostics.cs
new file mode 100644
index 00000000000..b473d0b2feb
--- /dev/null
+++ b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/Subscriptions/SubscriptionTestDiagnostics.cs
@@ -0,0 +1,108 @@
+using HotChocolate.Subscriptions.Diagnostics;
+
+namespace HotChocolate.AspNetCore.Subscriptions;
+
+public sealed class SubscriptionTestDiagnostics : SubscriptionDiagnosticEventsListener
+{
+ private readonly object _sync = new();
+ private readonly List<(int Count, TaskCompletionSource Signal)> _subscribedSignals = [];
+ private readonly List<(int Count, TaskCompletionSource Signal)> _unsubscribeSignals = [];
+ private readonly List<(int Count, TaskCompletionSource Signal)> _closeSignals = [];
+ private int _subscribed;
+ private int _unsubscribeCount;
+ private int _closeCount;
+
+ public int Subscribed => _subscribed;
+
+ public bool UnsubscribeInvoked { get; private set; }
+
+ public bool CloseInvoked { get; private set; }
+
+ public override void SubscribeSuccess(string topicName)
+ {
+ var subscribed = Interlocked.Increment(ref _subscribed);
+ SignalCompleted(_subscribedSignals, subscribed);
+ }
+
+ public override void Unsubscribe(string topicName, int shard, int subscribers)
+ {
+ UnsubscribeInvoked = true;
+ var unsubscribeCount = Interlocked.Increment(ref _unsubscribeCount);
+ SignalCompleted(_unsubscribeSignals, unsubscribeCount);
+ }
+
+ public override void Close(string topicName)
+ {
+ CloseInvoked = true;
+ var closeCount = Interlocked.Increment(ref _closeCount);
+ SignalCompleted(_closeSignals, closeCount);
+ }
+
+ public Task WaitForSubscribedAsync(CancellationToken cancellationToken)
+ => WaitForSubscribedAsync(1, cancellationToken);
+
+ public Task WaitForSubscribedAsync(int count, CancellationToken cancellationToken)
+ => WaitForSignalAsync(_subscribedSignals, count, _subscribed, cancellationToken);
+
+ public Task WaitForUnsubscribeAsync(CancellationToken cancellationToken)
+ => WaitForUnsubscribeAsync(1, cancellationToken);
+
+ public Task WaitForUnsubscribeAsync(int count, CancellationToken cancellationToken)
+ => WaitForSignalAsync(_unsubscribeSignals, count, _unsubscribeCount, cancellationToken);
+
+ public Task WaitForCloseAsync(CancellationToken cancellationToken)
+ => WaitForCloseAsync(1, cancellationToken);
+
+ public Task WaitForCloseAsync(int count, CancellationToken cancellationToken)
+ => WaitForSignalAsync(_closeSignals, count, _closeCount, cancellationToken);
+
+ private Task WaitForSignalAsync(
+ List<(int Count, TaskCompletionSource Signal)> signals,
+ int count,
+ int currentCount,
+ CancellationToken cancellationToken)
+ {
+ if (currentCount >= count)
+ {
+ return Task.CompletedTask;
+ }
+
+ TaskCompletionSource signal;
+
+ lock (_sync)
+ {
+ if (GetCurrentCount(signals) >= count)
+ {
+ return Task.CompletedTask;
+ }
+
+ signal = new(TaskCreationOptions.RunContinuationsAsynchronously);
+ signals.Add((count, signal));
+ }
+
+ return signal.Task.WaitAsync(cancellationToken);
+ }
+
+ private int GetCurrentCount(List<(int Count, TaskCompletionSource Signal)> signals)
+ => ReferenceEquals(signals, _subscribedSignals)
+ ? _subscribed
+ : ReferenceEquals(signals, _unsubscribeSignals)
+ ? _unsubscribeCount
+ : _closeCount;
+
+ private void SignalCompleted(List<(int Count, TaskCompletionSource Signal)> signals, int count)
+ {
+ TaskCompletionSource[] ready;
+
+ lock (_sync)
+ {
+ ready = [.. signals.Where(t => t.Count <= count).Select(t => t.Signal)];
+ signals.RemoveAll(t => t.Count <= count);
+ }
+
+ foreach (var signal in ready)
+ {
+ signal.TrySetResult();
+ }
+ }
+}
diff --git a/src/HotChocolate/AspNetCore/test/Transport.Sockets.Client.Tests/GraphQLOverWebSocket/WebSocketClientBatchTests.cs b/src/HotChocolate/AspNetCore/test/Transport.Sockets.Client.Tests/GraphQLOverWebSocket/WebSocketClientBatchTests.cs
index 71c7d193b5b..a5934addc66 100644
--- a/src/HotChocolate/AspNetCore/test/Transport.Sockets.Client.Tests/GraphQLOverWebSocket/WebSocketClientBatchTests.cs
+++ b/src/HotChocolate/AspNetCore/test/Transport.Sockets.Client.Tests/GraphQLOverWebSocket/WebSocketClientBatchTests.cs
@@ -10,7 +10,7 @@ public class WebSocketClientBatchTests(TestServerFactory serverFactory, ITestOut
{
[Fact]
public Task ExecuteBatch_ReceivesAllResults()
- => TryTest(async ct =>
+ => RunTest(async ct =>
{
// arrange
using var testServer = CreateStarWarsServer(output: output);
@@ -44,7 +44,7 @@ public Task ExecuteBatch_ReceivesAllResults()
[Fact]
public Task ExecuteBatch_SingleRequest_WorksLikeSingleExecute()
- => TryTest(async ct =>
+ => RunTest(async ct =>
{
// arrange
using var testServer = CreateStarWarsServer(output: output);
@@ -75,7 +75,7 @@ public Task ExecuteBatch_SingleRequest_WorksLikeSingleExecute()
[Fact]
public Task ExecuteBatch_Should_Throw_When_Socket_Aborted_Without_Close_Frame()
{
- return TryTest(async ct =>
+ return RunTest(async ct =>
{
// arrange
var subscriptionRequest = new OperationBatchRequest(
diff --git a/src/HotChocolate/AspNetCore/test/Transport.Sockets.Client.Tests/GraphQLOverWebSocket/WebSocketClientProtocolTests.cs b/src/HotChocolate/AspNetCore/test/Transport.Sockets.Client.Tests/GraphQLOverWebSocket/WebSocketClientProtocolTests.cs
index 2f24ca3ce08..27c16d1888d 100644
--- a/src/HotChocolate/AspNetCore/test/Transport.Sockets.Client.Tests/GraphQLOverWebSocket/WebSocketClientProtocolTests.cs
+++ b/src/HotChocolate/AspNetCore/test/Transport.Sockets.Client.Tests/GraphQLOverWebSocket/WebSocketClientProtocolTests.cs
@@ -94,7 +94,7 @@ public Task Subscribe_ReceiveDataOnMutation()
[Fact]
public Task Subscribe_Should_Throw_When_Socket_Aborted_Without_Close_Frame()
{
- return TryTest(async ct =>
+ return RunTest(async ct =>
{
// arrange
var subscriptionRequest = new OperationRequest(
@@ -129,7 +129,7 @@ async Task ReadResults()
[Fact]
public Task ReadResultsAsync_Should_Complete_When_Execute_Token_Is_Canceled()
{
- return TryTest(async ct =>
+ return RunTest(async ct =>
{
// arrange
var subscriptionRequest = new OperationRequest(
@@ -169,7 +169,7 @@ public Task ReadResultsAsync_Should_Complete_When_Execute_Token_Is_Canceled()
[Fact]
public Task ReadResultsAsync_Should_Throw_SocketClosedException_When_Server_Closes_Connection()
{
- return TryTest(async ct =>
+ return RunTest(async ct =>
{
// arrange
var subscriptionRequest = new OperationRequest(
@@ -199,7 +199,7 @@ async Task ReadResults()
[Fact]
public Task ReadResultsAsync_Should_Throw_SocketClosedException_When_Server_Closes_Connection_After_Next_Messages()
{
- return TryTest(async ct =>
+ return RunTest(async ct =>
{
// arrange
var subscriptionRequest = new OperationRequest(
@@ -232,7 +232,7 @@ async Task ReadResults()
[Fact]
public Task ReadResultsAsync_Should_Throw_SocketClosedException_When_Connection_Is_Lost_Without_Close_Frame()
{
- return TryTest(async ct =>
+ return RunTest(async ct =>
{
// arrange
var subscriptionRequest = new OperationRequest(
@@ -276,7 +276,7 @@ public Task ReadResultsAsync_Should_Throw_SocketClosedException_When_Connection_
[Fact]
public Task DisposeAsync_Should_Complete_Stream_Cleanly()
{
- return TryTest(async ct =>
+ return RunTest(async ct =>
{
// arrange
var subscriptionRequest = new OperationRequest(
@@ -318,7 +318,7 @@ public Task DisposeAsync_Should_Complete_Stream_Cleanly()
[Fact]
public Task ReadResultsAsync_Should_Throw_SocketClosedException_When_Server_Sends_Structurally_Invalid_Message()
{
- return TryTest(async ct =>
+ return RunTest(async ct =>
{
// arrange
var subscriptionRequest = new OperationRequest(
@@ -352,7 +352,7 @@ async Task ReadResults()
[Fact]
public Task ReadResultsAsync_Should_Throw_SocketClosedException_When_Server_Sends_Unknown_Message_Type()
{
- return TryTest(async ct =>
+ return RunTest(async ct =>
{
// arrange
var subscriptionRequest = new OperationRequest(
@@ -386,7 +386,7 @@ async Task ReadResults()
[Fact]
public Task ReadResultsAsync_Should_Yield_Result_When_Next_Message_Type_Follows_Payload()
{
- return TryTest(async ct =>
+ return RunTest(async ct =>
{
// arrange
var subscriptionRequest = new OperationRequest(
@@ -430,7 +430,7 @@ public Task Send_Subscribe_SyntaxError()
{
var snapshot = new Snapshot();
- return TryTest(async ct =>
+ return RunTest(async ct =>
{
// arrange
var subscriptionRequest = new OperationRequest(
@@ -462,7 +462,7 @@ public Task Send_Subscribe_ValidationError()
{
var snapshot = new Snapshot();
- return TryTest(async ct =>
+ return RunTest(async ct =>
{
// arrange
var subscriptionRequest = new OperationRequest(
@@ -491,7 +491,7 @@ public Task Send_Subscribe_ValidationError()
[Fact]
public Task Send_Connect_With_Auth_Accept()
- => TryTest(async ct =>
+ => RunTest(async ct =>
{
// arrange
var interceptor = new AuthInterceptor();
@@ -515,7 +515,7 @@ await SocketClient.ConnectAsync(
[Fact]
public Task Send_Connect_With_Auth_Reject()
- => TryTest(async ct =>
+ => RunTest(async ct =>
{
// arrange
var interceptor = new AuthInterceptor();
@@ -538,7 +538,7 @@ public Task Send_Connect_With_Auth_Reject()
[Fact]
public Task ConnectAsync_Should_TearDown_Socket_When_Handshake_Is_Canceled()
{
- return TryTest(async ct =>
+ return RunTest(async ct =>
{
// arrange
// the server accepts the socket but never sends a connection_ack, so the client's
diff --git a/src/HotChocolate/Caching/test/Caching.Tests/TestServerFactory.cs b/src/HotChocolate/Caching/test/Caching.Tests/TestServerFactory.cs
index 9f2cc5e598a..2fb3b2d2956 100644
--- a/src/HotChocolate/Caching/test/Caching.Tests/TestServerFactory.cs
+++ b/src/HotChocolate/Caching/test/Caching.Tests/TestServerFactory.cs
@@ -1,32 +1,36 @@
using Microsoft.AspNetCore.Builder;
-using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
namespace HotChocolate.Caching.Http.Tests;
-public class TestServerFactory : IDisposable
+public class TestServerFactory : IAsyncDisposable
{
- private readonly List _instances = [];
+ private readonly List _instances = [];
public TestServer Create(
Action configureServices,
Action configureApplication)
{
- var builder = new WebHostBuilder()
- .Configure(configureApplication)
- .ConfigureServices(configureServices);
+ var builder = WebApplication.CreateEmptyBuilder(new WebApplicationOptions());
+ builder.WebHost.UseTestServer();
+ configureServices(builder.Services);
- var server = new TestServer(builder);
- _instances.Add(server);
- return server;
+ var app = builder.Build();
+ configureApplication(app);
+
+ app.Start();
+ _instances.Add(app);
+ return app.GetTestServer();
}
- public void Dispose()
+ public async ValueTask DisposeAsync()
{
- foreach (var testServer in _instances)
+ foreach (var app in _instances)
{
- testServer.Dispose();
+ await app.StopAsync();
+ await app.DisposeAsync();
}
}
}
diff --git a/src/HotChocolate/Data/test/Data.Sorting.InMemory.Tests/QueryableSortVisitorVariablesTests.cs b/src/HotChocolate/Data/test/Data.Sorting.InMemory.Tests/QueryableSortVisitorVariablesTests.cs
index 3b1a3b2e178..40a114ec01a 100644
--- a/src/HotChocolate/Data/test/Data.Sorting.InMemory.Tests/QueryableSortVisitorVariablesTests.cs
+++ b/src/HotChocolate/Data/test/Data.Sorting.InMemory.Tests/QueryableSortVisitorVariablesTests.cs
@@ -1,8 +1,8 @@
using HotChocolate.AspNetCore.Tests.Utilities;
using Microsoft.AspNetCore.Builder;
-using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
using HotChocolate.Execution;
using HotChocolate.Types;
@@ -221,33 +221,32 @@ private TestServer CreateServer(TEntity?[] entities)
where TEntity : class
where T : SortInputType
{
- var builder = new WebHostBuilder()
- .ConfigureServices(
- (_, services) =>
+ var builder = WebApplication.CreateSlimBuilder();
+ builder.WebHost.UseTestServer();
+ builder.Services.AddRouting();
+ builder.Services.AddGraphQLServer()
+ .ModifyCostOptions(o => o.DefaultListSize = 1)
+ .AddSorting()
+ .AddQueryType(
+ c =>
{
- services.AddRouting();
- services.AddGraphQLServer()
- .ModifyCostOptions(o => o.DefaultListSize = 1)
- .AddSorting()
- .AddQueryType(
- c =>
- {
- c
- .Name("Query")
- .Field("root")
- .Resolve(entities)
- .UseSorting();
-
- c
- .Name("Query")
- .Field("rootExecutable")
- .Resolve(entities.AsExecutable())
- .UseSorting();
- })
- .BuildRequestExecutorAsync();
+ c
+ .Name("Query")
+ .Field("root")
+ .Resolve(entities)
+ .UseSorting();
+
+ c
+ .Name("Query")
+ .Field("rootExecutable")
+ .Resolve(entities.AsExecutable())
+ .UseSorting();
})
- .Configure(x => x.UseRouting().UseEndpoints(c => c.MapGraphQL()));
- return new TestServer(builder);
+ .BuildRequestExecutorAsync();
+ var app = builder.Build();
+ app.MapGraphQL();
+ app.Start();
+ return app.GetTestServer();
}
private ValueTask CreateSchema(TEntity?[] entities)
diff --git a/src/HotChocolate/Diagnostics/test/Diagnostics.Tests/McpAdapterActivityTests.cs b/src/HotChocolate/Diagnostics/test/Diagnostics.Tests/McpAdapterActivityTests.cs
index b0407fc13d8..6d7f44ed072 100644
--- a/src/HotChocolate/Diagnostics/test/Diagnostics.Tests/McpAdapterActivityTests.cs
+++ b/src/HotChocolate/Diagnostics/test/Diagnostics.Tests/McpAdapterActivityTests.cs
@@ -4,9 +4,9 @@
using HotChocolate.Language;
using HotChocolate.Resolvers;
using Microsoft.AspNetCore.Builder;
-using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
using ModelContextProtocol.Client;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
@@ -23,8 +23,8 @@ public partial class McpAdapterActivityTests
public async Task Mcp_CallTool()
{
// arrange
- using var server = CreateServer("query GetBook { book { title } }");
- var mcpClient = await CreateMcpClientAsync(server.CreateClient());
+ await using var app = StartApp("query GetBook { book { title } }");
+ var mcpClient = await CreateMcpClientAsync(app.GetTestClient());
await mcpClient.ListToolsAsync(cancellationToken: TestContext.Current.CancellationToken);
using (CaptureActivities(out var activities))
@@ -41,8 +41,8 @@ public async Task Mcp_CallTool()
public async Task Mcp_CallTool_Field_Does_Not_Exist()
{
// arrange
- using var server = CreateServer("query InvalidGraphqlQuery { doesNotExist }");
- var mcpClient = await CreateMcpClientAsync(server.CreateClient());
+ await using var app = StartApp("query InvalidGraphqlQuery { doesNotExist }");
+ var mcpClient = await CreateMcpClientAsync(app.GetTestClient());
await mcpClient.ListToolsAsync(cancellationToken: TestContext.Current.CancellationToken);
using (CaptureActivities(out var activities))
@@ -61,8 +61,8 @@ await mcpClient.CallToolAsync(
public async Task Mcp_CallTool_Tool_Does_Not_Exist()
{
// arrange
- using var server = CreateServer("query GetBook { book { title } }");
- var mcpClient = await CreateMcpClientAsync(server.CreateClient());
+ await using var app = StartApp("query GetBook { book { title } }");
+ var mcpClient = await CreateMcpClientAsync(app.GetTestClient());
await mcpClient.ListToolsAsync(cancellationToken: TestContext.Current.CancellationToken);
using (CaptureActivities(out var activities))
@@ -79,8 +79,8 @@ public async Task Mcp_CallTool_Tool_Does_Not_Exist()
public async Task Mcp_CallTool_GraphQL_Field_Error()
{
// arrange
- using var server = CreateServer("query GetFaultyBook { faultyBook { title } }");
- var mcpClient = await CreateMcpClientAsync(server.CreateClient());
+ await using var app = StartApp("query GetFaultyBook { faultyBook { title } }");
+ var mcpClient = await CreateMcpClientAsync(app.GetTestClient());
await mcpClient.ListToolsAsync(cancellationToken: TestContext.Current.CancellationToken);
using (CaptureActivities(out var activities))
@@ -97,8 +97,8 @@ public async Task Mcp_CallTool_GraphQL_Field_Error()
public async Task Mcp_GetPrompt()
{
// arrange
- using var server = CreateServer(prompt: CreateGreetingPrompt());
- var mcpClient = await CreateMcpClientAsync(server.CreateClient());
+ await using var app = StartApp(prompt: CreateGreetingPrompt());
+ var mcpClient = await CreateMcpClientAsync(app.GetTestClient());
await mcpClient.ListPromptsAsync(cancellationToken: TestContext.Current.CancellationToken);
using (CaptureActivities(out var activities))
@@ -159,28 +159,25 @@ private static PromptDefinition CreateGreetingPrompt()
]
};
- private static TestServer CreateServer(string? toolDocument = null, PromptDefinition? prompt = null)
+ private static WebApplication StartApp(string? toolDocument = null, PromptDefinition? prompt = null)
{
var storage = new InMemoryMcpStorage(toolDocument, prompt);
- var builder = new WebHostBuilder()
- .ConfigureServices(services =>
- {
- services.AddRouting();
- services
- .AddGraphQLServer()
- .AddInstrumentation()
- .AddMcp()
- .AddMcpStorage(storage)
- .AddQueryType();
- })
- .Configure(app =>
- {
- app.UseRouting();
- app.UseEndpoints(endpoints => endpoints.MapGraphQLMcp());
- });
-
- return new TestServer(builder);
+ var builder = WebApplication.CreateSlimBuilder();
+ builder.WebHost.UseTestServer();
+ builder.Services.AddRouting();
+ builder.Services
+ .AddGraphQLServer()
+ .AddInstrumentation()
+ .AddMcp()
+ .AddMcpStorage(storage)
+ .AddQueryType();
+
+ var app = builder.Build();
+ app.MapGraphQLMcp();
+ app.Start();
+
+ return app;
}
private static async Task CreateMcpClientAsync(HttpClient httpClient)
diff --git a/src/HotChocolate/Diagnostics/test/Diagnostics.Tests/OpenApiAdapterActivityTests.cs b/src/HotChocolate/Diagnostics/test/Diagnostics.Tests/OpenApiAdapterActivityTests.cs
index 3aac96089d0..d43ae14377f 100644
--- a/src/HotChocolate/Diagnostics/test/Diagnostics.Tests/OpenApiAdapterActivityTests.cs
+++ b/src/HotChocolate/Diagnostics/test/Diagnostics.Tests/OpenApiAdapterActivityTests.cs
@@ -4,9 +4,9 @@
using HotChocolate.Language;
using HotChocolate.Resolvers;
using Microsoft.AspNetCore.Builder;
-using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
using static CookieCrumble.TestEnvironment;
using static HotChocolate.Diagnostics.ActivityTestHelper;
@@ -21,7 +21,7 @@ public async Task Http_Get_OpenApi()
using (CaptureActivities(out var activities))
{
// arrange
- using var server = CreateServer(
+ await using var app = StartApp(
"""
query GetBook @http(method: GET, route: "/book") {
book {
@@ -29,7 +29,7 @@ query GetBook @http(method: GET, route: "/book") {
}
}
""");
- using var client = server.CreateClient();
+ using var client = app.GetTestClient();
// act
using var response = await client.GetAsync("/book", TestContext.Current.CancellationToken);
@@ -46,13 +46,13 @@ public async Task Http_Get_OpenApi_Field_Does_Not_Exist()
using (CaptureActivities(out var activities))
{
// arrange
- using var server = CreateServer(
+ await using var app = StartApp(
"""
query GetMissing @http(method: GET, route: "/invalid-graphql-query") {
doesNotExist
}
""");
- using var client = server.CreateClient();
+ using var client = app.GetTestClient();
// act
using var response = await client.GetAsync("/invalid-graphql-query", TestContext.Current.CancellationToken);
@@ -69,7 +69,7 @@ public async Task Http_Get_OpenApi_Endpoint_Does_Not_Exist()
using (CaptureActivities(out var activities))
{
// arrange
- using var server = CreateServer(
+ await using var app = StartApp(
"""
query GetBook @http(method: GET, route: "/book") {
book {
@@ -77,7 +77,7 @@ query GetBook @http(method: GET, route: "/book") {
}
}
""");
- using var client = server.CreateClient();
+ using var client = app.GetTestClient();
// act
using var response = await client.GetAsync("/does-not-exist", TestContext.Current.CancellationToken);
@@ -95,7 +95,7 @@ public async Task Http_Get_OpenApi_GraphQL_Field_Error()
using (CaptureActivities(out var activities))
{
// arrange
- using var server = CreateServer(
+ await using var app = StartApp(
"""
query GetFaultyBook @http(method: GET, route: "/faulty-book") {
faultyBook {
@@ -103,7 +103,7 @@ query GetFaultyBook @http(method: GET, route: "/faulty-book") {
}
}
""");
- using var client = server.CreateClient();
+ using var client = app.GetTestClient();
// act
using var response = await client.GetAsync("/faulty-book", TestContext.Current.CancellationToken);
@@ -114,28 +114,25 @@ query GetFaultyBook @http(method: GET, route: "/faulty-book") {
}
}
- private static TestServer CreateServer(params string[] documents)
+ private static WebApplication StartApp(params string[] documents)
{
var storage = new InMemoryOpenApiDefinitionStorage(documents);
- var builder = new WebHostBuilder()
- .ConfigureServices(services =>
- {
- services.AddRouting();
- services
- .AddGraphQLServer()
- .AddInstrumentation()
- .AddOpenApi()
- .AddOpenApiDefinitionStorage(storage)
- .AddQueryType();
- })
- .Configure(app =>
- {
- app.UseRouting();
- app.UseEndpoints(endpoints => endpoints.MapOpenApiEndpoints());
- });
-
- return new TestServer(builder);
+ var builder = WebApplication.CreateSlimBuilder();
+ builder.WebHost.UseTestServer();
+ builder.Services.AddRouting();
+ builder.Services
+ .AddGraphQLServer()
+ .AddInstrumentation()
+ .AddOpenApi()
+ .AddOpenApiDefinitionStorage(storage)
+ .AddQueryType();
+
+ var app = builder.Build();
+ app.MapOpenApiEndpoints();
+ app.Start();
+
+ return app;
}
public class Query
diff --git a/src/HotChocolate/Fusion/test/Fusion.AspNetCore.Tests/FusionTestBase.cs b/src/HotChocolate/Fusion/test/Fusion.AspNetCore.Tests/FusionTestBase.cs
index 8df479647b3..24a8657716e 100644
--- a/src/HotChocolate/Fusion/test/Fusion.AspNetCore.Tests/FusionTestBase.cs
+++ b/src/HotChocolate/Fusion/test/Fusion.AspNetCore.Tests/FusionTestBase.cs
@@ -28,7 +28,7 @@
namespace HotChocolate.Fusion;
-public abstract partial class FusionTestBase : IDisposable
+public abstract partial class FusionTestBase : IAsyncDisposable
{
private readonly TestServerSession _testServerSession = new();
private bool _disposed;
@@ -265,7 +265,7 @@ SourceSchemaInteraction GetSourceSchemaInteraction(OperationPlanContext context,
}
}
- public void Dispose()
+ public async ValueTask DisposeAsync()
{
if (_disposed)
{
@@ -273,18 +273,10 @@ public void Dispose()
}
_disposed = true;
- Dispose(true);
+ await _testServerSession.DisposeAsync();
GC.SuppressFinalize(this);
}
- protected virtual void Dispose(bool disposing)
- {
- if (disposing)
- {
- _testServerSession.Dispose();
- }
- }
-
protected class Gateway : IDisposable
{
internal Gateway(
diff --git a/src/HotChocolate/Fusion/test/Fusion.AspNetCore.Tests/SpecOnlyCompositionGatewayTests.cs b/src/HotChocolate/Fusion/test/Fusion.AspNetCore.Tests/SpecOnlyCompositionGatewayTests.cs
index eb2340b5d6a..1066b1482bf 100644
--- a/src/HotChocolate/Fusion/test/Fusion.AspNetCore.Tests/SpecOnlyCompositionGatewayTests.cs
+++ b/src/HotChocolate/Fusion/test/Fusion.AspNetCore.Tests/SpecOnlyCompositionGatewayTests.cs
@@ -53,7 +53,7 @@ public async Task SpecOnlySources_Should_LoadAndPriceFoldedDirectives_When_Gatew
var compositeDocument = compositeSchema.ToSyntaxNode();
await using var executionSchema = FusionSchemaDefinition.Create(compositeDocument);
- using var session = new TestServerSession();
+ await using var session = new TestServerSession();
using var gateway = CreateGateway(session, compositeDocument);
var request = new OperationRequest("{ items { value } }");
diff --git a/src/HotChocolate/Fusion/test/Fusion.AspNetCore.Tests/TestServerSession.cs b/src/HotChocolate/Fusion/test/Fusion.AspNetCore.Tests/TestServerSession.cs
index 89794bd9fed..6a23cf7f480 100644
--- a/src/HotChocolate/Fusion/test/Fusion.AspNetCore.Tests/TestServerSession.cs
+++ b/src/HotChocolate/Fusion/test/Fusion.AspNetCore.Tests/TestServerSession.cs
@@ -1,14 +1,14 @@
using System.Threading.Channels;
using Microsoft.AspNetCore.Builder;
-using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
namespace HotChocolate.Fusion;
-internal sealed class TestServerSession : IDisposable
+internal sealed class TestServerSession : IAsyncDisposable
{
- private readonly Channel _cleanupPipeline = Channel.CreateUnbounded();
+ private readonly Channel _cleanupPipeline = Channel.CreateUnbounded();
private bool _disposed;
public TestServer CreateServer(
@@ -16,28 +16,27 @@ public TestServer CreateServer(
Action configureApplication,
string? environmentName = null)
{
- var builder = new WebHostBuilder()
- .Configure(configureApplication)
- .ConfigureServices(configureServices);
+ var builder = WebApplication.CreateEmptyBuilder(
+ new WebApplicationOptions { EnvironmentName = environmentName });
+ builder.WebHost.UseTestServer();
+ configureServices(builder.Services);
- if (environmentName is not null)
- {
- builder.UseEnvironment(environmentName);
- }
+ var app = builder.Build();
+ configureApplication(app);
- var server = new TestServer(builder);
+ app.Start();
- if (!_cleanupPipeline.Writer.TryWrite(server))
+ if (!_cleanupPipeline.Writer.TryWrite(app))
{
- server.Dispose();
+ ((IHost)app).Dispose();
throw new InvalidOperationException(
"Failed to add test server to cleanup pipeline.");
}
- return server;
+ return app.GetTestServer();
}
- public void Dispose()
+ public async ValueTask DisposeAsync()
{
if (_disposed)
{
@@ -48,9 +47,10 @@ public void Dispose()
_cleanupPipeline.Writer.TryComplete();
- while (_cleanupPipeline.Reader.TryRead(out var server))
+ while (_cleanupPipeline.Reader.TryRead(out var app))
{
- server.Dispose();
+ await app.StopAsync();
+ await app.DisposeAsync();
}
}
}
diff --git a/src/HotChocolate/Fusion/test/Fusion.Connectors.InMemory.Tests/FileUploadTests.cs b/src/HotChocolate/Fusion/test/Fusion.Connectors.InMemory.Tests/FileUploadTests.cs
index 9e0ce9d60ea..c5904453e6c 100644
--- a/src/HotChocolate/Fusion/test/Fusion.Connectors.InMemory.Tests/FileUploadTests.cs
+++ b/src/HotChocolate/Fusion/test/Fusion.Connectors.InMemory.Tests/FileUploadTests.cs
@@ -5,23 +5,21 @@
using HotChocolate.Transport.Http;
using HotChocolate.Types;
using Microsoft.AspNetCore.Builder;
-using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
using OperationRequest = HotChocolate.Transport.OperationRequest;
namespace HotChocolate.Fusion;
-public sealed class FileUploadTests : IDisposable
+public sealed class FileUploadTests
{
- private TestServer? _server;
-
[Fact]
public async Task Upload_Single_File()
{
// arrange
- _server = await CreateServerAsync();
- using var client = GraphQLHttpClient.Create(_server.CreateClient());
+ await using var app = StartApp();
+ using var client = GraphQLHttpClient.Create(app.GetTestClient());
var stream = new MemoryStream("abc"u8.ToArray());
@@ -102,8 +100,8 @@ public async Task Upload_Single_File_Should_KeepText_When_TextSpansArenaSegments
public async Task Upload_Single_File_In_Input_Object()
{
// arrange
- _server = await CreateServerAsync();
- using var client = GraphQLHttpClient.Create(_server.CreateClient());
+ await using var app = StartApp();
+ using var client = GraphQLHttpClient.Create(app.GetTestClient());
var stream = new MemoryStream("abc"u8.ToArray());
@@ -143,8 +141,8 @@ public async Task Upload_Single_File_In_Input_Object()
public async Task Upload_Single_File_In_Input_Object_Inline()
{
// arrange
- _server = await CreateServerAsync();
- using var client = GraphQLHttpClient.Create(_server.CreateClient());
+ await using var app = StartApp();
+ using var client = GraphQLHttpClient.Create(app.GetTestClient());
var stream = new MemoryStream("abc"u8.ToArray());
@@ -181,8 +179,8 @@ public async Task Upload_Single_File_In_Input_Object_Inline()
public async Task Upload_List_Of_Files()
{
// arrange
- _server = await CreateServerAsync();
- using var client = GraphQLHttpClient.Create(_server.CreateClient());
+ await using var app = StartApp();
+ using var client = GraphQLHttpClient.Create(app.GetTestClient());
var stream1 = new MemoryStream("abc"u8.ToArray());
var stream2 = new MemoryStream("def"u8.ToArray());
@@ -224,8 +222,8 @@ public async Task Upload_List_Of_Files()
public async Task Upload_List_Of_Files_In_Input_Object()
{
// arrange
- _server = await CreateServerAsync();
- using var client = GraphQLHttpClient.Create(_server.CreateClient());
+ await using var app = StartApp();
+ using var client = GraphQLHttpClient.Create(app.GetTestClient());
var stream1 = new MemoryStream("abc"u8.ToArray());
var stream2 = new MemoryStream("abc"u8.ToArray());
@@ -270,8 +268,8 @@ public async Task Upload_List_Of_Files_In_Input_Object()
public async Task Upload_List_Of_Files_In_Input_Object_Inline()
{
// arrange
- _server = await CreateServerAsync();
- using var client = GraphQLHttpClient.Create(_server.CreateClient());
+ await using var app = StartApp();
+ using var client = GraphQLHttpClient.Create(app.GetTestClient());
var stream1 = new MemoryStream("abc"u8.ToArray());
var stream2 = new MemoryStream("def"u8.ToArray());
@@ -309,34 +307,28 @@ public async Task Upload_List_Of_Files_In_Input_Object_Inline()
body.MatchMarkdownSnapshot();
}
- private static Task CreateServerAsync()
+ private static WebApplication StartApp()
{
- var builder = new WebHostBuilder()
- .ConfigureServices(services =>
- {
- services.AddRouting();
-
- services.AddGraphQLServer("uploads")
- .AddQueryType()
- .AddUploadType()
- .ModifyCostOptions(o => o.DefaultListSize = 1)
- .AddSourceSchemaDefaults();
-
- services.AddGraphQLGatewayServer()
- .AddInMemorySchema("uploads");
- })
- .Configure(app =>
- {
- app.UseRouting();
- app.UseEndpoints(endpoints => endpoints.MapGraphQL());
- });
+ var builder = WebApplication.CreateSlimBuilder();
+ builder.WebHost.UseTestServer();
+ builder.Services.AddRouting();
- return Task.FromResult(new TestServer(builder));
- }
+ builder.Services
+ .AddGraphQLServer("uploads")
+ .AddQueryType()
+ .AddUploadType()
+ .ModifyCostOptions(o => o.DefaultListSize = 1)
+ .AddSourceSchemaDefaults();
- public void Dispose()
- {
- _server?.Dispose();
+ builder.Services
+ .AddGraphQLGatewayServer()
+ .AddInMemorySchema("uploads");
+
+ var app = builder.Build();
+ app.MapGraphQL();
+ app.Start();
+
+ return app;
}
private static class UploadSchema
diff --git a/src/HotChocolate/Fusion/test/Fusion.Execution.Tests/FusionTestBase.cs b/src/HotChocolate/Fusion/test/Fusion.Execution.Tests/FusionTestBase.cs
index bf0cb5349e0..f1bbaef4a31 100644
--- a/src/HotChocolate/Fusion/test/Fusion.Execution.Tests/FusionTestBase.cs
+++ b/src/HotChocolate/Fusion/test/Fusion.Execution.Tests/FusionTestBase.cs
@@ -19,7 +19,7 @@
namespace HotChocolate.Fusion;
-public abstract class FusionTestBase : IDisposable
+public abstract class FusionTestBase : IAsyncDisposable
{
private readonly TestServerSession _testServerSession = new();
private bool _disposed;
@@ -545,7 +545,7 @@ protected static void MatchSnapshot(
actual.MatchSnapshot(extension: ".yaml");
}
- public void Dispose()
+ public async ValueTask DisposeAsync()
{
if (_disposed)
{
@@ -553,18 +553,10 @@ public void Dispose()
}
_disposed = true;
- Dispose(true);
+ await _testServerSession.DisposeAsync();
GC.SuppressFinalize(this);
}
- protected virtual void Dispose(bool disposing)
- {
- if (disposing)
- {
- _testServerSession.Dispose();
- }
- }
-
private static List CreateSourceSchemaTexts(IEnumerable schemas)
{
var sourceSchemas = new List();
diff --git a/src/HotChocolate/Fusion/test/Fusion.Execution.Tests/TestServerSession.cs b/src/HotChocolate/Fusion/test/Fusion.Execution.Tests/TestServerSession.cs
index 4c17a23c69f..d9b32b2a1f2 100644
--- a/src/HotChocolate/Fusion/test/Fusion.Execution.Tests/TestServerSession.cs
+++ b/src/HotChocolate/Fusion/test/Fusion.Execution.Tests/TestServerSession.cs
@@ -1,37 +1,40 @@
using System.Threading.Channels;
using Microsoft.AspNetCore.Builder;
-using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
namespace HotChocolate.Fusion;
-internal sealed class TestServerSession : IDisposable
+internal sealed class TestServerSession : IAsyncDisposable
{
- private readonly Channel _cleanupPipeline = Channel.CreateUnbounded();
+ private readonly Channel _cleanupPipeline = Channel.CreateUnbounded();
private bool _disposed;
public TestServer CreateServer(
Action configureServices,
Action configureApplication)
{
- var builder = new WebHostBuilder()
- .Configure(configureApplication)
- .ConfigureServices(configureServices);
+ var builder = WebApplication.CreateEmptyBuilder(new WebApplicationOptions());
+ builder.WebHost.UseTestServer();
+ configureServices(builder.Services);
- var server = new TestServer(builder);
+ var app = builder.Build();
+ configureApplication(app);
- if (!_cleanupPipeline.Writer.TryWrite(server))
+ app.Start();
+
+ if (!_cleanupPipeline.Writer.TryWrite(app))
{
- server.Dispose();
+ ((IHost)app).Dispose();
throw new InvalidOperationException(
"Failed to add test server to cleanup pipeline.");
}
- return server;
+ return app.GetTestServer();
}
- public void Dispose()
+ public async ValueTask DisposeAsync()
{
if (_disposed)
{
@@ -42,9 +45,10 @@ public void Dispose()
_cleanupPipeline.Writer.TryComplete();
- while (_cleanupPipeline.Reader.TryRead(out var server))
+ while (_cleanupPipeline.Reader.TryRead(out var app))
{
- server.Dispose();
+ await app.StopAsync();
+ await app.DisposeAsync();
}
}
}
diff --git a/src/Nitro/CommandLine/src/CommandLine/Commands/Fusion/FusionRunCommand.cs b/src/Nitro/CommandLine/src/CommandLine/Commands/Fusion/FusionRunCommand.cs
index de6f7c39aa3..d466c218e61 100644
--- a/src/Nitro/CommandLine/src/CommandLine/Commands/Fusion/FusionRunCommand.cs
+++ b/src/Nitro/CommandLine/src/CommandLine/Commands/Fusion/FusionRunCommand.cs
@@ -51,42 +51,40 @@ private static async Task ExecuteAsync(
port ??= GetRandomUnusedPort();
- // Type or member is obsolete
-#pragma warning disable ASPDEPR008
- var host = new WebHostBuilder()
- .UseKestrel()
- .UseUrls(new UriBuilder("http", "localhost", port.Value).ToString())
- .ConfigureServices(services =>
+ var builder = WebApplication.CreateEmptyBuilder(
+ new WebApplicationOptions
{
- services
- .AddCors()
- .AddHeaderPropagation(c =>
- {
- c.Headers.Add("GraphQL-Preflight");
- c.Headers.Add("Authorization");
- });
-
- services
- .AddHttpClient("fusion")
- .AddHeaderPropagation();
-
- services.AddRouting()
- .AddGraphQLGatewayServer()
- .AddFileSystemConfiguration(archiveFilePath)
- .ModifyRequestOptions(o => o.CollectOperationPlanTelemetry = true)
- .ModifyServerOptions(o => o.Tool.ServeMode = App.ServeMode.Insider);
- })
- .Configure(app =>
+ EnvironmentName = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")
+ });
+ builder.WebHost.UseKestrelCore();
+ builder.WebHost.UseUrls(new UriBuilder("http", "localhost", port.Value).ToString());
+
+ builder.Services
+ .AddCors()
+ .AddHeaderPropagation(c =>
{
- app.UseRouting();
- app.UseHeaderPropagation();
- app.UseCors(c => c.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin());
- app.UseEndpoints(e => e.MapGraphQL());
- })
- .Build();
-#pragma warning restore ASPDEPR008
+ c.Headers.Add("GraphQL-Preflight");
+ c.Headers.Add("Authorization");
+ });
- var lifetime = host.Services.GetRequiredService();
+ builder.Services
+ .AddHttpClient("fusion")
+ .AddHeaderPropagation();
+
+ builder.Services
+ .AddRouting()
+ .AddGraphQLGatewayServer()
+ .AddFileSystemConfiguration(archiveFilePath)
+ .ModifyRequestOptions(o => o.CollectOperationPlanTelemetry = true)
+ .ModifyServerOptions(o => o.Tool.ServeMode = App.ServeMode.Insider);
+
+ var app = builder.Build();
+ app.UseRouting();
+ app.UseHeaderPropagation();
+ app.UseCors(c => c.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin());
+ app.MapGraphQL();
+
+ var lifetime = app.Services.GetRequiredService();
lifetime.ApplicationStarted.Register(() =>
{
@@ -119,7 +117,7 @@ private static async Task ExecuteAsync(
}
});
- await host.RunAsync(cancellationToken);
+ await app.RunAsync(cancellationToken);
return ExitCodes.Success;
}
diff --git a/src/Nitro/CommandLine/src/CommandLine/Helpers/SystemBrowser.cs b/src/Nitro/CommandLine/src/CommandLine/Helpers/SystemBrowser.cs
index 151e799caa6..fdb71275e19 100644
--- a/src/Nitro/CommandLine/src/CommandLine/Helpers/SystemBrowser.cs
+++ b/src/Nitro/CommandLine/src/CommandLine/Helpers/SystemBrowser.cs
@@ -7,6 +7,7 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.Hosting;
using static ChilliCream.Nitro.CommandLine.Helpers.OidcConfiguration;
namespace ChilliCream.Nitro.CommandLine.Helpers;
@@ -122,18 +123,18 @@ private static int GetRandomUnusedPort()
{
private const int DefaultTimeout = 60 * 10; // 10 mins (in seconds)
- private readonly IWebHost _host;
+ private readonly WebApplication _app;
private readonly TaskCompletionSource _source = new();
public LoopbackHttpListener(int port, string? path = null)
{
- _host = new WebHostBuilder()
- .UseKestrel()
- .UseUrls(new UriBuilder("http", "localhost", port, path).ToString())
- .Configure(app => app.Run(Execute))
- .Build();
+ var builder = WebApplication.CreateEmptyBuilder(new WebApplicationOptions());
+ builder.WebHost.UseKestrelCore();
+ builder.WebHost.UseUrls(new UriBuilder("http", "localhost", port, path).ToString());
- _host.Start();
+ _app = builder.Build();
+ _app.Run(Execute);
+ _app.Start();
}
public async ValueTask DisposeAsync()
@@ -145,7 +146,8 @@ public async ValueTask DisposeAsync()
}
_source.Task.Dispose();
- _host.Dispose();
+ await _app.StopAsync();
+ await _app.DisposeAsync();
}
private async Task Execute(HttpContext ctx)
diff --git a/src/StrawberryShake/Client/test/Transport.WebSocket.Tests/IntegrationTests.cs b/src/StrawberryShake/Client/test/Transport.WebSocket.Tests/IntegrationTests.cs
index a0adf2ca7c3..a8f7d6eb7e7 100644
--- a/src/StrawberryShake/Client/test/Transport.WebSocket.Tests/IntegrationTests.cs
+++ b/src/StrawberryShake/Client/test/Transport.WebSocket.Tests/IntegrationTests.cs
@@ -24,7 +24,7 @@ public async Task Simple_Request()
.Create(
async (snapshot, ct) =>
{
- using var host = TestServerHelper.CreateServer(
+ await using var app = TestServerHelper.StartApp(
x => x.AddTypeExtension(),
out var port);
@@ -60,7 +60,7 @@ public async Task Execution_Error()
.Create(
async (snapshot, ct) =>
{
- using var host = TestServerHelper.CreateServer(
+ await using var app = TestServerHelper.StartApp(
x => x.AddTypeExtension(),
out var port);
@@ -96,7 +96,7 @@ public async Task Validation_Error()
.Create(
async (snapshot, ct) =>
{
- using var host = TestServerHelper.CreateServer(
+ await using var app = TestServerHelper.StartApp(
x => x.AddTypeExtension(),
out var port);
@@ -134,7 +134,7 @@ public async Task Request_With_ConnectionPayload()
{
var payload = new Dictionary { ["Key"] = "Value" };
var sessionInterceptor = new StubSessionInterceptor();
- using var host = TestServerHelper.CreateServer(
+ await using var app = TestServerHelper.StartApp(
builder => builder
.AddTypeExtension()
.AddSocketSessionInterceptor(
@@ -180,8 +180,8 @@ public async Task Parallel_Request_SameSocket()
async (snapshot, ct) =>
{
// arrange
- using var host = TestServerHelper
- .CreateServer(
+ await using var app = TestServerHelper
+ .StartApp(
x => x.AddTypeExtension(),
out var port);
diff --git a/src/StrawberryShake/Client/test/Transport.WebSocket.Tests/TestHelper/TestServerHelper.cs b/src/StrawberryShake/Client/test/Transport.WebSocket.Tests/TestHelper/TestServerHelper.cs
index 7f58c3df65d..8921bedda9b 100644
--- a/src/StrawberryShake/Client/test/Transport.WebSocket.Tests/TestHelper/TestServerHelper.cs
+++ b/src/StrawberryShake/Client/test/Transport.WebSocket.Tests/TestHelper/TestServerHelper.cs
@@ -5,106 +5,99 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
-using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
namespace StrawberryShake.Transport.WebSockets;
public static class TestServerHelper
{
- public static IWebHost CreateServer(Action configure, out int port)
+ public static WebApplication StartApp(Action configure, out int port)
{
for (port = 5500; port < 6000; port++)
{
try
{
- var configBuilder = new ConfigurationBuilder();
- configBuilder.AddInMemoryCollection();
- var config = configBuilder.Build();
- config["server.urls"] = $"http://localhost:{port}";
- var host = new WebHostBuilder()
- .UseConfiguration(config)
- .UseKestrel()
- .ConfigureServices(
- services =>
- {
- var builder = services
- .AddRouting()
- .AddGraphQLServer()
- .ModifyCostOptions(o => o.DefaultListSize = 1);
-
- configure(builder);
+ var builder = WebApplication.CreateEmptyBuilder(new WebApplicationOptions());
+ builder.WebHost.UseKestrelCore();
+ builder.WebHost.UseUrls($"http://localhost:{port}");
- builder
- .AddStarWarsTypes()
- .DisableIntrospection(disable: false)
- .AddStarWarsRepositories()
- .AddInMemorySubscriptions()
- .ModifyOptions(
- o =>
- {
- o.EnableDefer = true;
- o.EnableStream = true;
- })
- .UseDefaultPipeline()
- .UseRequest(
- next => async context =>
- {
- if (context.ContextData.TryGetValue(
- nameof(HttpContext),
- out var value)
- && value is HttpContext httpContext
- && context.Result is OperationResult result)
- {
- var headers = httpContext.Request.Headers;
- if (headers.ContainsKey("sendErrorStatusCode"))
- {
- result.ContextData =
- result.ContextData.SetItem(
- ExecutionContextData.HttpStatusCode,
- 403);
- }
+ var gqlBuilder = builder.Services
+ .AddRouting()
+ .AddGraphQLServer()
+ .ModifyCostOptions(o => o.DefaultListSize = 1);
- if (headers.ContainsKey("sendError"))
- {
- result.Errors = result.Errors.Add(
- new Error { Message = "Some error!" });
- }
- }
+ configure(gqlBuilder);
- await next(context);
- });
+ gqlBuilder
+ .AddStarWarsTypes()
+ .DisableIntrospection(disable: false)
+ .AddStarWarsRepositories()
+ .AddInMemorySubscriptions()
+ .ModifyOptions(
+ o =>
+ {
+ o.EnableDefer = true;
+ o.EnableStream = true;
})
- .Configure(
- app =>
- app.Use(async (ct, next) =>
+ .UseDefaultPipeline()
+ .UseRequest(
+ next => async context =>
+ {
+ if (context.ContextData.TryGetValue(
+ nameof(HttpContext),
+ out var value)
+ && value is HttpContext httpContext
+ && context.Result is OperationResult result)
{
- try
+ var headers = httpContext.Request.Headers;
+ if (headers.ContainsKey("sendErrorStatusCode"))
{
- // Kestrel does not return proper error responses:
- // https://github.com/aspnet/KestrelHttpServer/issues/43
- await next();
+ result.ContextData =
+ result.ContextData.SetItem(
+ ExecutionContextData.HttpStatusCode,
+ 403);
}
- catch (Exception ex)
- {
- if (ct.Response.HasStarted)
- {
- throw;
- }
- ct.Response.StatusCode = 500;
- ct.Response.Headers.Clear();
- await ct.Response.WriteAsync(ex.ToString());
+ if (headers.ContainsKey("sendError"))
+ {
+ result.Errors = result.Errors.Add(
+ new Error { Message = "Some error!" });
}
- })
- .UseWebSockets()
- .UseRouting()
- .UseEndpoints(e => e.MapGraphQL()))
- .Build();
+ }
+
+ await next(context);
+ });
+
+ var app = builder.Build();
+
+ app.Use(async (ct, next) =>
+ {
+ try
+ {
+ // Kestrel does not return proper error responses:
+ // https://github.com/aspnet/KestrelHttpServer/issues/43
+ await next();
+ }
+ catch (Exception ex)
+ {
+ if (ct.Response.HasStarted)
+ {
+ throw;
+ }
+
+ ct.Response.StatusCode = 500;
+ ct.Response.Headers.Clear();
+ await ct.Response.WriteAsync(ex.ToString());
+ }
+ });
+ app.UseWebSockets();
+ app.UseRouting();
+ app.MapGraphQL();
- host.Start();
+ app.Start();
- return host;
+ return app;
}
catch
{
diff --git a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/AnyScalarDefaultSerializationTest.cs b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/AnyScalarDefaultSerializationTest.cs
index f81b11d920e..c903712952c 100644
--- a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/AnyScalarDefaultSerializationTest.cs
+++ b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/AnyScalarDefaultSerializationTest.cs
@@ -17,7 +17,7 @@ public async Task Execute_AnyScalarDefaultSerialization_Test()
{
// arrange
using var cts = new CancellationTokenSource(20_000);
- using var host = TestServerHelper.CreateServer(
+ await using var app = TestServerHelper.StartApp(
builder => builder.AddTypeExtension().AddJsonTypeConverter(),
out var port);
var serviceCollection = new ServiceCollection();
diff --git a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/LocalTypesTest.cs b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/LocalTypesTest.cs
index 82d9ddbc87c..01e43a21297 100644
--- a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/LocalTypesTest.cs
+++ b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/LocalTypesTest.cs
@@ -17,7 +17,7 @@ public async Task Execute_LocalTypes_Test()
{
// arrange
var ct = new CancellationTokenSource(20_000).Token;
- using var host = TestServerHelper.CreateServer(
+ await using var app = TestServerHelper.StartApp(
builder => builder.AddTypeExtension(typeof(QueryType)),
out var port);
var serviceCollection = new ServiceCollection();
diff --git a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/MultiProfileTest.cs b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/MultiProfileTest.cs
index bc749b664af..b8f6d08aa8d 100644
--- a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/MultiProfileTest.cs
+++ b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/MultiProfileTest.cs
@@ -14,7 +14,7 @@ public MultiProfileTest(TestServerFactory serverFactory) : base(serverFactory)
public void Execute_MultiProfile_Test()
{
// arrange
- using var host = TestServerHelper.CreateServer(
+ using var app = TestServerHelper.StartApp(
_ => { },
out var port);
var serviceCollection = new ServiceCollection();
diff --git a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsGetFriendsDeferInListTest.cs b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsGetFriendsDeferInListTest.cs
index 6879353ea6c..ee52fcb1433 100644
--- a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsGetFriendsDeferInListTest.cs
+++ b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsGetFriendsDeferInListTest.cs
@@ -14,7 +14,7 @@ public async Task Execute_StarWarsGetFriendsDeferInList_Test()
{
// arrange
CancellationToken ct = new CancellationTokenSource(20_000).Token;
- using IWebHost host = TestServerHelper.CreateServer(
+ using var app = TestServerHelper.StartApp(
_ => { },
out var port);
var serviceCollection = new ServiceCollection();
diff --git a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsGetFriendsDeferredTest.cs b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsGetFriendsDeferredTest.cs
index 8b48f7258f4..ebc548da258 100644
--- a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsGetFriendsDeferredTest.cs
+++ b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsGetFriendsDeferredTest.cs
@@ -14,7 +14,7 @@ public async Task Execute_StarWarsGetFriendsDeferred_Test()
{
// arrange
CancellationToken ct = new CancellationTokenSource(20_000).Token;
- using IWebHost host = TestServerHelper.CreateServer(
+ using var app = TestServerHelper.StartApp(
_ => { },
out var port);
var serviceCollection = new ServiceCollection();
diff --git a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsGetFriendsNoStoreTest.cs b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsGetFriendsNoStoreTest.cs
index b1e09dcbf6b..41596a355f7 100644
--- a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsGetFriendsNoStoreTest.cs
+++ b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsGetFriendsNoStoreTest.cs
@@ -16,7 +16,7 @@ public async Task Execute_StarWarsGetFriendsNoStore_Test()
{
// arrange
var ct = new CancellationTokenSource(20_000).Token;
- using var host = TestServerHelper.CreateServer(
+ await using var app = TestServerHelper.StartApp(
_ => { },
out var port);
var serviceCollection = new ServiceCollection();
diff --git a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsGetFriendsTest.cs b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsGetFriendsTest.cs
index 4cc5dc99000..3aea5d13a61 100644
--- a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsGetFriendsTest.cs
+++ b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsGetFriendsTest.cs
@@ -15,7 +15,7 @@ public async Task Execute_StarWarsGetFriends_Test()
{
// arrange
var ct = new CancellationTokenSource(20_000).Token;
- using var host = TestServerHelper.CreateServer(_ => { }, out var port);
+ await using var app = TestServerHelper.StartApp(_ => { }, out var port);
var serviceCollection = new ServiceCollection();
serviceCollection
@@ -45,7 +45,7 @@ public async Task Execute_StarWarsGetFriends_WithRequestUri_Test()
{
// arrange
var ct = new CancellationTokenSource(20_000).Token;
- using var host = TestServerHelper.CreateServer(_ => { }, out var port);
+ await using var app = TestServerHelper.StartApp(_ => { }, out var port);
var serviceCollection = new ServiceCollection();
serviceCollection
@@ -72,7 +72,7 @@ public async Task Execute_StarWarsGetFriends_WithHttpClient_Test()
{
// arrange
var ct = new CancellationTokenSource(20_000).Token;
- using var host = TestServerHelper.CreateServer(_ => { }, out var port);
+ await using var app = TestServerHelper.StartApp(_ => { }, out var port);
var serviceCollection = new ServiceCollection();
serviceCollection
@@ -102,7 +102,7 @@ public async Task Execute_StarWarsGetFriends_Test_404()
{
// arrange
var ct = new CancellationTokenSource(20_000).Token;
- using var host = TestServerHelper.CreateServer(_ => { }, out var port);
+ await using var app = TestServerHelper.StartApp(_ => { }, out var port);
var serviceCollection = new ServiceCollection();
serviceCollection
@@ -129,7 +129,7 @@ public async Task Execute_StarWarsGetFriends_Test_403_And_Success_Content_1()
{
// arrange
var ct = new CancellationTokenSource(20_000).Token;
- using var host = TestServerHelper.CreateServer(
+ await using var app = TestServerHelper.StartApp(
_ => { },
out var port);
var serviceCollection = new ServiceCollection();
@@ -172,7 +172,7 @@ public async Task Execute_StarWarsGetFriends_Test_403_And_Success_Content_2()
{
// arrange
var ct = new CancellationTokenSource(20_000).Token;
- using var host = TestServerHelper.CreateServer(
+ await using var app = TestServerHelper.StartApp(
_ => { },
out var port);
var serviceCollection = new ServiceCollection();
diff --git a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsGetHeroTest.cs b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsGetHeroTest.cs
index a2f38bbd649..51c10be51fa 100644
--- a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsGetHeroTest.cs
+++ b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsGetHeroTest.cs
@@ -18,7 +18,7 @@ public async Task Execute_StarWarsGetHero_Test()
{
// arrange
var ct = new CancellationTokenSource(20_000).Token;
- using var host = TestServerHelper.CreateServer(
+ await using var app = TestServerHelper.StartApp(
_ => { },
out var port);
var serviceCollection = new ServiceCollection();
@@ -45,7 +45,7 @@ public async Task Watch_StarWarsGetHero_Test()
{
// arrange
var ct = new CancellationTokenSource(20_000).Token;
- using var host = TestServerHelper.CreateServer(
+ await using var app = TestServerHelper.StartApp(
_ => { },
out var port);
var serviceCollection = new ServiceCollection();
@@ -82,7 +82,7 @@ public async Task Watch_CacheFirst_StarWarsGetHero_Test()
{
// arrange
var ct = new CancellationTokenSource(20_000).Token;
- using var host = TestServerHelper.CreateServer(
+ await using var app = TestServerHelper.StartApp(
_ => { },
out var port);
var serviceCollection = new ServiceCollection();
@@ -121,7 +121,7 @@ public async Task Watch_Interact_With_Store()
{
// arrange
using var cts = new CancellationTokenSource(20_000);
- using var host = TestServerHelper.CreateServer(
+ await using var app = TestServerHelper.StartApp(
_ => { },
out var port);
var serviceCollection = new ServiceCollection();
@@ -190,7 +190,7 @@ public async Task Watch_Interact_With_Persistence()
{
// arrange
using var cts = new CancellationTokenSource(100_20_000);
- using var host = TestServerHelper.CreateServer(
+ await using var app = TestServerHelper.StartApp(
_ => { },
out var port);
var serviceCollection = new ServiceCollection();
@@ -256,7 +256,7 @@ public async Task Watch_Interact_With_Persistence()
{
// arrange
using var cts = new CancellationTokenSource(100_20_000);
- using var host = TestServerHelper.CreateServer(
+ await using var app = TestServerHelper.StartApp(
_ => { },
out var port);
var serviceCollection = new ServiceCollection();
@@ -303,7 +303,7 @@ public async Task Update_Once()
{
// arrange
var ct = new CancellationTokenSource(20_000).Token;
- using var host = TestServerHelper.CreateServer(
+ await using var app = TestServerHelper.StartApp(
_ => { },
out var port);
var serviceCollection = new ServiceCollection();
@@ -338,7 +338,7 @@ public async Task Update_Once_With_Cache_And_Network()
{
// arrange
var ct = new CancellationTokenSource(20_000).Token;
- using var host = TestServerHelper.CreateServer(
+ await using var app = TestServerHelper.StartApp(
_ => { },
out var port);
var serviceCollection = new ServiceCollection();
diff --git a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsGetHeroTraitsTest.cs b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsGetHeroTraitsTest.cs
index 0e404a06f65..ecdad9b0f65 100644
--- a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsGetHeroTraitsTest.cs
+++ b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsGetHeroTraitsTest.cs
@@ -15,7 +15,7 @@ public async Task Execute_StarWarsGetHeroTraits_Test()
{
// arrange
var ct = new CancellationTokenSource(20_000).Token;
- using var host = TestServerHelper.CreateServer(
+ await using var app = TestServerHelper.StartApp(
_ => { },
out var port);
var serviceCollection = new ServiceCollection();
diff --git a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsGetHeroWithFragmentIncludeAndSkipDirectiveTest.cs b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsGetHeroWithFragmentIncludeAndSkipDirectiveTest.cs
index f4b48455f6b..f94fae12f6d 100644
--- a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsGetHeroWithFragmentIncludeAndSkipDirectiveTest.cs
+++ b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsGetHeroWithFragmentIncludeAndSkipDirectiveTest.cs
@@ -15,7 +15,7 @@ public async Task Execute_StarWarsGetHeroWithFragmentIncludeAndSkipDirective_Tes
{
// arrange
var ct = new CancellationTokenSource(20_000).Token;
- using var host = TestServerHelper.CreateServer(
+ await using var app = TestServerHelper.StartApp(
_ => { },
out var port);
var serviceCollection = new ServiceCollection();
diff --git a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsIntrospectionTest.cs b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsIntrospectionTest.cs
index 8a70f4de852..e1f7dbd2dac 100644
--- a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsIntrospectionTest.cs
+++ b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsIntrospectionTest.cs
@@ -15,7 +15,7 @@ public async Task Execute_StarWarsIntrospection_Test()
{
// arrange
var ct = new CancellationTokenSource(20_000).Token;
- using var host = TestServerHelper.CreateServer(
+ await using var app = TestServerHelper.StartApp(
_ => { },
out var port);
var serviceCollection = new ServiceCollection();
diff --git a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsOnReviewSubCompletionTest.cs b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsOnReviewSubCompletionTest.cs
index 2bb167bf847..56c1579d10e 100644
--- a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsOnReviewSubCompletionTest.cs
+++ b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsOnReviewSubCompletionTest.cs
@@ -18,8 +18,8 @@ public class StarWarsOnReviewSubCompletionTest(TestServerFactory serverFactory)
public async Task Watch_StarWarsOnReviewSubCompletion_Test()
{
// arrange
- using var host = TestServerHelper.CreateServer(_ => { }, out var port);
- var topicEventSender = host.Services.GetRequiredService();
+ await using var app = TestServerHelper.StartApp(_ => { }, out var port);
+ var topicEventSender = app.Services.GetRequiredService();
var serviceCollection = new ServiceCollection();
serviceCollection.AddStarWarsOnReviewSubCompletionClient(
@@ -74,10 +74,10 @@ await topicEventSender.SendAsync(
public async Task Watch_StarWarsOnReviewSubCompletionPassively_Test()
{
// arrange
- using var host = TestServerHelper.CreateServer(
+ await using var app = TestServerHelper.StartApp(
_ => { },
out var port);
- var topicEventSender = host.Services.GetRequiredService();
+ var topicEventSender = app.Services.GetRequiredService();
var serviceCollection = new ServiceCollection();
serviceCollection.AddStarWarsOnReviewSubCompletionClient(
@@ -118,7 +118,7 @@ await topicEventSender.SendAsync(
var monitor = services.GetRequiredService();
monitor.AbortSocket();
- //await host.StopAsync();
+ //await app.StopAsync();
// waiting for completion message sent
for (var times = 0; !completionTriggered && times < 10; times++)
diff --git a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsOnReviewSubGraphQLSSETest.cs b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsOnReviewSubGraphQLSSETest.cs
index ebe6319529d..aac7d9922f3 100644
--- a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsOnReviewSubGraphQLSSETest.cs
+++ b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsOnReviewSubGraphQLSSETest.cs
@@ -19,7 +19,7 @@ public async Task Execute_StarWarsOnReviewSubGraphQLSSE_Test()
// arrange
using var cts = new CancellationTokenSource(20_000);
var ct = cts.Token;
- using var host = TestServerHelper.CreateServer(
+ await using var app = TestServerHelper.StartApp(
_ => { },
out var port);
var serviceCollection = new ServiceCollection();
@@ -34,7 +34,7 @@ public async Task Execute_StarWarsOnReviewSubGraphQLSSE_Test()
var client = services.GetRequiredService();
// act
- var topicEventSender = host.Services.GetRequiredService();
+ var topicEventSender = app.Services.GetRequiredService();
const Episode topic = Episode.NewHope;
var connectCompletionSource = new TaskCompletionSource();
diff --git a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsOnReviewSubNoStoreTest.cs b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsOnReviewSubNoStoreTest.cs
index 44414be0b22..245c3c9d1a0 100644
--- a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsOnReviewSubNoStoreTest.cs
+++ b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsOnReviewSubNoStoreTest.cs
@@ -18,7 +18,7 @@ public async Task Watch_StarWarsOnReviewSubNoStore_NotifyCompletion()
{
// arrange
using var cts = new CancellationTokenSource(20_000);
- using var host = TestServerHelper.CreateServer(_ => { }, out var port);
+ await using var app = TestServerHelper.StartApp(_ => { }, out var port);
var ct = cts.Token;
var serviceCollection = new ServiceCollection();
@@ -33,7 +33,7 @@ public async Task Watch_StarWarsOnReviewSubNoStore_NotifyCompletion()
var client = services.GetRequiredService();
// act
- var topicEventSender = host.Services.GetRequiredService();
+ var topicEventSender = app.Services.GetRequiredService();
const Episode topic = Episode.NewHope;
var connectCompletionSource = new TaskCompletionSource();
diff --git a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsTypeNameOnInterfacesTest.cs b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsTypeNameOnInterfacesTest.cs
index 59c2b4f5bd5..09e2bd36cc8 100644
--- a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsTypeNameOnInterfacesTest.cs
+++ b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsTypeNameOnInterfacesTest.cs
@@ -17,7 +17,7 @@ public async Task Execute_StarWarsTypeNameOnInterfaces_Test()
// arrange
using var cts = new CancellationTokenSource(20_000);
- using var host = TestServerHelper.CreateServer(
+ await using var app = TestServerHelper.StartApp(
_ => { },
out var port);
var serviceCollection = new ServiceCollection();
diff --git a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsTypeNameOnUnionsTest.cs b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsTypeNameOnUnionsTest.cs
index 2a0db3b6aa3..549bdab8965 100644
--- a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsTypeNameOnUnionsTest.cs
+++ b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsTypeNameOnUnionsTest.cs
@@ -15,7 +15,7 @@ public async Task Execute_StarWarsTypeNameOnUnions_Test()
{
// arrange
var cts = new CancellationTokenSource(20_000);
- using var host = TestServerHelper.CreateServer(
+ await using var app = TestServerHelper.StartApp(
_ => { },
out var port);
var serviceCollection = new ServiceCollection();
diff --git a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsUnionListTest.cs b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsUnionListTest.cs
index c0ed1a1945d..b74e2b4c7ac 100644
--- a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsUnionListTest.cs
+++ b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/StarWarsUnionListTest.cs
@@ -16,7 +16,7 @@ public async Task Execute_StarWarsUnionList_Test()
// arrange
using var cts = new CancellationTokenSource(20_000);
- using var host = TestServerHelper.CreateServer(
+ await using var app = TestServerHelper.StartApp(
_ => { },
out var port);
var serviceCollection = new ServiceCollection();
diff --git a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/UnsignedTypesTest.cs b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/UnsignedTypesTest.cs
index 6e22176a36a..fd1f48e042f 100644
--- a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/UnsignedTypesTest.cs
+++ b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/UnsignedTypesTest.cs
@@ -16,7 +16,7 @@ public async Task Execute_UnsignedTypes_Test()
{
// arrange
var ct = new CancellationTokenSource(20_000).Token;
- using var host = TestServerHelper.CreateServer(
+ await using var app = TestServerHelper.StartApp(
builder => builder.AddTypeExtension(typeof(QueryType)),
out var port);
var serviceCollection = new ServiceCollection();
diff --git a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/UploadScalarTest.cs b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/UploadScalarTest.cs
index a662fc6cd7f..b3ae7972b19 100644
--- a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/UploadScalarTest.cs
+++ b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/Integration/UploadScalarTest.cs
@@ -1,5 +1,5 @@
using HotChocolate.AspNetCore.Tests.Utilities;
-using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using StrawberryShake.Transport.WebSockets;
using static StrawberryShake.CodeGeneration.CSharp.Integration.UploadScalar.UploadSchemaHelpers;
@@ -19,8 +19,8 @@ public async Task Execute_UploadScalar_Argument(string? contentType)
{
// arrange
var ct = new CancellationTokenSource(20_000).Token;
- using var host = TestServerHelper.CreateServer(Configure, out var port);
- var client = CreateClient(host, port);
+ await using var app = TestServerHelper.StartApp(Configure, out var port);
+ var client = CreateClient(app, port);
await using var data = CreateStream("a");
// act
@@ -45,8 +45,8 @@ public async Task Execute_UploadScalarList_Argument(string? contentType)
{
// arrange
var ct = new CancellationTokenSource(20_000).Token;
- using var host = TestServerHelper.CreateServer(Configure, out var port);
- var client = CreateClient(host, port);
+ await using var app = TestServerHelper.StartApp(Configure, out var port);
+ var client = CreateClient(app, port);
await using var dataA = CreateStream("a");
await using var dataB = CreateStream("b");
@@ -72,8 +72,8 @@ public async Task Execute_UploadScalarNested_Argument(string? contentType)
{
// arrange
var ct = new CancellationTokenSource(20_000).Token;
- using var host = TestServerHelper.CreateServer(Configure, out var port);
- var client = CreateClient(host, port);
+ await using var app = TestServerHelper.StartApp(Configure, out var port);
+ var client = CreateClient(app, port);
await using var dataA = CreateStream("a");
await using var dataB = CreateStream("b");
@@ -99,8 +99,8 @@ public async Task Execute_Input_Argument(string? contentType)
{
// arrange
var ct = new CancellationTokenSource(20_000).Token;
- using var host = TestServerHelper.CreateServer(Configure, out var port);
- var client = CreateClient(host, port);
+ await using var app = TestServerHelper.StartApp(Configure, out var port);
+ var client = CreateClient(app, port);
await using var data = CreateStream("a");
// act
@@ -131,8 +131,8 @@ public async Task Execute_InputList_Argument(string? contentType)
{
// arrange
var ct = new CancellationTokenSource(20_000).Token;
- using var host = TestServerHelper.CreateServer(Configure, out var port);
- var client = CreateClient(host, port);
+ await using var app = TestServerHelper.StartApp(Configure, out var port);
+ var client = CreateClient(app, port);
await using var dataA = CreateStream("a");
await using var dataB = CreateStream("b");
// act
@@ -173,8 +173,8 @@ public async Task Execute_InputNested_Argument(string? contentType)
{
// arrange
var ct = new CancellationTokenSource(20_000).Token;
- using var host = TestServerHelper.CreateServer(Configure, out var port);
- var client = CreateClient(host, port);
+ await using var app = TestServerHelper.StartApp(Configure, out var port);
+ var client = CreateClient(app, port);
await using var dataA = CreateStream("a");
await using var dataB = CreateStream("b");
@@ -212,7 +212,7 @@ public async Task Execute_InputNested_Argument(string? contentType)
Assert.Equal($"[A:a|{contentType}],[B:b|{contentType}]", result.Data!.Upload);
}
- public static UploadScalarClient CreateClient(IWebHost host, int port)
+ public static UploadScalarClient CreateClient(WebApplication app, int port)
{
var serviceCollection = new ServiceCollection();
serviceCollection.AddHttpClient(
@@ -237,8 +237,8 @@ public async Task Execute_ListWorksWithNull(string? contentType)
{
// arrange
var ct = new CancellationTokenSource(20_000).Token;
- using var host = TestServerHelper.CreateServer(Configure, out var port);
- var client = CreateClient(host, port);
+ await using var app = TestServerHelper.StartApp(Configure, out var port);
+ var client = CreateClient(app, port);
await using var dataA = CreateStream("a");
await using var dataB = CreateStream("b");
diff --git a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__resources__/TestTemplate.txt b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__resources__/TestTemplate.txt
index 8b302fa78cd..dd75d7d25e6 100644
--- a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__resources__/TestTemplate.txt
+++ b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__resources__/TestTemplate.txt
@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using HotChocolate.AspNetCore.Tests.Utilities;
-using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using StrawberryShake.Transport.WebSockets;
@@ -20,7 +19,7 @@ public class {TestName}Test : ServerTestBase
{
// arrange
CancellationToken ct = new CancellationTokenSource(20_000).Token;
- using IWebHost host = TestServerHelper.CreateServer(
+ using var app = TestServerHelper.StartApp(
_ => { },
out var port);
var serviceCollection = new ServiceCollection();