Provide examples/samples on how to customize Host in ASP NET Core 6 Minimal APIs
Help us make content visible
- Keywords I tried: "minimal testing custom host", "minimal testing override host"
- I expected these to contain information on the issue:
- https://docs.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-6.0#customize-webapplicationfactory
- https://docs.microsoft.com/en-us/aspnet/core/migration/50-to-60-samples?view=aspnetcore-6.0#test-with-webapplicationfactory-or-testserver
Describe the new topic
- Being able to customize the Host configuration in integration tests is useful to avoid calling services that shouldn't run at all during testing. This was easily achievable using the standard Startup model, overriding the
CreateHostBuilderfrom theWebApplicationFactory. I tried many many things using the "Minimal APIs" approach and couldn't figure it out.
A full example of what was possible using the Startup model, would be something like this:
Program.cs:
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); })
// This is a service that downloads Configuration from the internet, to be used
// as a source for `IConfiguration`, just like any `appsettings.json`.
// I don't want this running during testing
.AddConfigServer();
}
As you can imagine, the AddConfigServer calls an external web server to download the configuration I want to use in my app startup, but I definitely don't want my integration tests calling this external web server for several reasons: don't want to depend on external services, don't want to hammer my config server with testing requests, don't want my server customizations to be exposed to my tests, etc.
Using the Startup model, I could easily change this behavior with this:
public class MyWebApplicationFactory : WebApplicationFactory<Program>
{
protected override IHostBuilder CreateHostBuilder() =>
Host.CreateDefaultBuilder()
// No AddConfigServer for my integration tests
.ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); });
}
//... other customizations
}
However, trying this same approach throws an exception on my integration test startup:
System.InvalidOperationException : No application configured. Please specify an application via IWebHostBuilder.UseStartup, IWebHostBuilder.Configure, or specifying the startup assembly via StartupAssemblyKey in the web host configuration.
Since I don't have a Startup class, I couldn't figure out how to properly do this. In fact, since this is common in all my web projects, I abandoned Minimal APIs altogether for the moment, until I figure out how to properly achieve this without a Startup class.
- I expect this to be in "ASP.NET Core > Test, debug, and troubleshoot > Integration tests in ASP.NET Core".
- Suggestion: How to override Host configuration in ASP NET Core 6 Minimal APIs hosting model.
See https://docs.microsoft.com/en-us/aspnet/core/migration/50-to-60-samples#twa
See https://docs.microsoft.com/en-us/aspnet/core/migration/50-to-60-samples#twa
Hi Rick, I linked to that documentation in my original post, but that page doesn't cover how to properly replace the "Host" part using the ASP NET 6 Minimal APIs model. There is no equivalent code to the CreateHostBuilder in the doc's sample.
This looks like a problem with no described solution in docs
I can't figure out how do it only with WebApplicationFactory like before, the only solution I figure out is define a Testing environment to skip this kind of host configuration at tests
type MyWebApplication() =
inherit WebApplicationFactory<Program>()
override _.ConfigureWebHost(builder: IWebHostBuilder) =
builder.seEnvironment("Testing") // new enviroment
|> ignore
if not app.Environment.IsEnvironment("Testing") then // check environment
app.UseSpaStaticFiles()
app.UseSpa(fun spa -> spa.UseReactDevelopmentServer("start"))
@javiercn please comment
We have a similar situation, with services that should be conditionally configured on application startup. These are currently implemented as virtual methods in Startup.
public class Startup {
public void ConfigureServices(IServiceCollection services) {
ConfigureHangfire();
}
protected virtual void ConfigureHangfire() {
// Some code that I don't want to run in integration tests, or I want to customize per test
}
}
Can't figure how to do this properly in ASP.NET Core 6. To my understanding this was a common pattern in the past, so we can't be the only ones.
Can anyone provide more info, please?