Skip to content

Commit 2470851

Browse files
committed
Account for modern apps that don't explicitly utilize the CreateWebHost startup model.
1 parent 3137cf2 commit 2470851

File tree

1 file changed

+54
-26
lines changed

1 file changed

+54
-26
lines changed

src/Mvc/Mvc.Testing/src/WebApplicationFactory.cs

Lines changed: 54 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using Microsoft.AspNetCore.Hosting;
1010
using Microsoft.AspNetCore.Hosting.Server;
1111
using Microsoft.AspNetCore.Hosting.Server.Features;
12+
using Microsoft.AspNetCore.Http.Features;
1213
using Microsoft.AspNetCore.Server.Kestrel.Core;
1314
using Microsoft.AspNetCore.TestHost;
1415
using Microsoft.Extensions.Configuration;
@@ -196,6 +197,32 @@ public void UseKestrel(Action<KestrelServerOptions> configureKestrelOptions)
196197
}
197198

198199
private IWebHost CreateKestrelServer(IWebHostBuilder builder)
200+
{
201+
ConfigureBuilderToUseKestrel(builder);
202+
203+
var host = builder.Build();
204+
205+
TryConfigureServerPort(() => GetServerAddressFeature(host));
206+
207+
host.Start();
208+
return host;
209+
}
210+
211+
private void TryConfigureServerPort(Func<IServerAddressesFeature?> serverAddressFeatureAccessor)
212+
{
213+
if (_kestrelPort.HasValue)
214+
{
215+
var saf = serverAddressFeatureAccessor();
216+
if (saf is not null)
217+
{
218+
saf.Addresses.Clear();
219+
saf.Addresses.Add($"http://127.0.0.1:{_kestrelPort}");
220+
saf.PreferHostingUrls = true;
221+
}
222+
}
223+
}
224+
225+
private void ConfigureBuilderToUseKestrel(IWebHostBuilder builder)
199226
{
200227
if (_configureKestrelOptions is not null)
201228
{
@@ -205,19 +232,6 @@ private IWebHost CreateKestrelServer(IWebHostBuilder builder)
205232
{
206233
builder.UseKestrel();
207234
}
208-
209-
var host = builder.Build();
210-
211-
if (_kestrelPort.HasValue)
212-
{
213-
var saf = host.Services.GetRequiredService<IServerAddressesFeature>();
214-
saf.Addresses.Clear();
215-
saf.Addresses.Add($"http://127.0.0.1:{_kestrelPort}");
216-
saf.PreferHostingUrls = true;
217-
}
218-
219-
host.Start();
220-
return host;
221235
}
222236

223237
/// <summary>
@@ -226,7 +240,7 @@ private IWebHost CreateKestrelServer(IWebHostBuilder builder)
226240
/// <exception cref="InvalidOperationException">Thrown if the provided <typeparamref name="TEntryPoint"/> type has no factory method.</exception>
227241
public void StartServer()
228242
{
229-
if (_server != null || _webHost != null)
243+
if (_webHost != null || _host != null)
230244
{
231245
return;
232246
}
@@ -288,13 +302,7 @@ public void StartServer()
288302
{
289303
_webHost = CreateKestrelServer(builder);
290304

291-
var serverAddressFeature = _webHost.ServerFeatures.Get<IServerAddressesFeature>();
292-
if (serverAddressFeature?.Addresses.Count > 0)
293-
{
294-
// Store the web host address as it's going to be used every time a client is created to communicate to the server
295-
_webHostAddress = new Uri(serverAddressFeature.Addresses.Last());
296-
ClientOptions.BaseAddress = _webHostAddress;
297-
}
305+
TryExtractHostAddress(() => GetServerAddressFeature(_webHost));
298306
}
299307
else
300308
{
@@ -303,23 +311,38 @@ public void StartServer()
303311
}
304312
}
305313

314+
private void TryExtractHostAddress(Func<IServerAddressesFeature?> serverAddressFeatureAccessor)
315+
{
316+
var serverAddressFeature = serverAddressFeatureAccessor();
317+
if (serverAddressFeature?.Addresses.Count > 0)
318+
{
319+
// Store the web host address as it's going to be used every time a client is created to communicate to the server
320+
_webHostAddress = new Uri(serverAddressFeature.Addresses.Last());
321+
ClientOptions.BaseAddress = _webHostAddress;
322+
}
323+
}
324+
306325
private void ConfigureHostBuilder(IHostBuilder hostBuilder)
307326
{
308327
hostBuilder.ConfigureWebHost(webHostBuilder =>
309328
{
310329
SetContentRoot(webHostBuilder);
311330
_configuration(webHostBuilder);
312-
if (!_useKestrel)
331+
if (_useKestrel)
313332
{
314-
webHostBuilder.UseTestServer();
333+
ConfigureBuilderToUseKestrel(webHostBuilder);
315334
}
316335
else
317336
{
318-
webHostBuilder.UseKestrel();
337+
webHostBuilder.UseTestServer();
319338
}
320339
});
321340
_host = CreateHost(hostBuilder);
322-
if (!_useKestrel)
341+
if (_useKestrel)
342+
{
343+
TryExtractHostAddress(() => GetServerAddressFeature(_host));
344+
}
345+
else
323346
{
324347
_server = (TestServer)_host.Services.GetRequiredService<IServer>();
325348
}
@@ -549,10 +572,15 @@ private static void EnsureDepsFile()
549572
protected virtual IHost CreateHost(IHostBuilder builder)
550573
{
551574
var host = builder.Build();
575+
TryConfigureServerPort(() => GetServerAddressFeature(host));
552576
host.Start();
553577
return host;
554578
}
555579

580+
private static IServerAddressesFeature? GetServerAddressFeature(IHost host) => host.Services.GetRequiredService<IServer>().Features.Get<IServerAddressesFeature>();
581+
582+
private static IServerAddressesFeature? GetServerAddressFeature(IWebHost webHost) => webHost.ServerFeatures.Get<IServerAddressesFeature>();
583+
556584
/// <summary>
557585
/// Gives a fixture an opportunity to configure the application before it gets built.
558586
/// </summary>
@@ -662,7 +690,7 @@ protected virtual void ConfigureClient(HttpClient client)
662690

663691
if (_useKestrel)
664692
{
665-
if (_webHost is null)
693+
if (_webHost is null && _host is null)
666694
{
667695
throw new InvalidOperationException(Resources.ServerNotInitialized);
668696
}

0 commit comments

Comments
 (0)