Skip to content

Commit c5f4ac0

Browse files
Add test for multiple ConfigureWebHost calls with UseStartup
Co-authored-by: BrennanConroy <[email protected]>
1 parent 71f4919 commit c5f4ac0

File tree

1 file changed

+79
-2
lines changed

1 file changed

+79
-2
lines changed

src/Hosting/Hosting/test/GenericWebHostBuilderTests.cs

Lines changed: 79 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using System.Linq;
5+
using Microsoft.AspNetCore.Builder;
56
using Microsoft.AspNetCore.Hosting.Server;
67
using Microsoft.AspNetCore.Hosting.Server.Features;
8+
using Microsoft.AspNetCore.Http;
79
using Microsoft.AspNetCore.Http.Features;
810
using Microsoft.Extensions.Configuration;
911
using Microsoft.Extensions.DependencyInjection;
@@ -128,6 +130,59 @@ public void ReadsUrlsOrPorts(string urls, string httpPorts, string httpsPorts, s
128130
Assert.Equal(expected, string.Join(';', server.Addresses));
129131
}
130132

133+
[Fact]
134+
public async Task MultipleConfigureWebHostCallsWithUseStartupLastWins()
135+
{
136+
var server = new TestServer();
137+
138+
using var host = new HostBuilder()
139+
.ConfigureWebHost(webHostBuilder =>
140+
{
141+
webHostBuilder
142+
.UseServer(server)
143+
.UseStartup<FirstStartup>();
144+
})
145+
.ConfigureWebHost(webHostBuilder =>
146+
{
147+
webHostBuilder
148+
.UseStartup<SecondStartup>();
149+
})
150+
.Build();
151+
152+
await host.StartAsync();
153+
await AssertResponseContains(server.RequestDelegate, "SecondStartup");
154+
}
155+
156+
private async Task AssertResponseContains(RequestDelegate app, string expectedText)
157+
{
158+
var httpContext = new DefaultHttpContext();
159+
httpContext.Response.Body = new MemoryStream();
160+
await app(httpContext);
161+
httpContext.Response.Body.Seek(0, SeekOrigin.Begin);
162+
var bodyText = new StreamReader(httpContext.Response.Body).ReadToEnd();
163+
Assert.Contains(expectedText, bodyText);
164+
}
165+
166+
private class FirstStartup
167+
{
168+
public void ConfigureServices(IServiceCollection services) { }
169+
170+
public void Configure(IApplicationBuilder app)
171+
{
172+
app.Run(context => context.Response.WriteAsync("FirstStartup"));
173+
}
174+
}
175+
176+
private class SecondStartup
177+
{
178+
public void ConfigureServices(IServiceCollection services) { }
179+
180+
public void Configure(IApplicationBuilder app)
181+
{
182+
app.Run(context => context.Response.WriteAsync("SecondStartup"));
183+
}
184+
}
185+
131186
private class TestServer : IServer, IServerAddressesFeature
132187
{
133188
public TestServer()
@@ -139,9 +194,31 @@ public TestServer()
139194

140195
public ICollection<string> Addresses { get; } = new List<string>();
141196
public bool PreferHostingUrls { get; set; }
197+
public RequestDelegate RequestDelegate { get; private set; }
142198

143-
public Task StartAsync<TContext>(IHttpApplication<TContext> application, CancellationToken cancellationToken) => Task.CompletedTask;
144-
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
145199
public void Dispose() { }
200+
201+
public Task StartAsync<TContext>(IHttpApplication<TContext> application, CancellationToken cancellationToken)
202+
{
203+
// For testing that uses RequestDelegate
204+
RequestDelegate = async ctx =>
205+
{
206+
var httpContext = application.CreateContext(ctx.Features);
207+
try
208+
{
209+
await application.ProcessRequestAsync(httpContext);
210+
}
211+
catch (Exception ex)
212+
{
213+
application.DisposeContext(httpContext, ex);
214+
throw;
215+
}
216+
application.DisposeContext(httpContext, null);
217+
};
218+
219+
return Task.CompletedTask;
220+
}
221+
222+
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
146223
}
147224
}

0 commit comments

Comments
 (0)