dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
35.22k stars 9.95k forks source link

WebApplicationFactory should enable ValidateScopes and ValidateOnBuild by default regardless of environment #56411

Open andrewjsaid opened 3 months ago

andrewjsaid commented 3 months ago

Is there an existing issue for this?

Is your feature request related to a problem? Please describe the problem.

In the context of WebApplicationFactory which is intended for testing, the service provider options ValidateScopes and ValidateOnBuild are not specifically set, and instead rely on the environment to be Development.

API Code: When run in dev mode this throws exception due to invalid DI setup.

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddSingleton<SingletonService>();
builder.Services.AddScoped<ScopedService>();

var app = builder.Build();

app.MapGet("/hello", () => "world");

app.Run();

public class SingletonService(ScopedService scoped) { }
public class ScopedService { }
public partial class Program { }

Test Code: E2E tests pass

using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Testing;

namespace TestProject;

public class UnitTest1
{
    [Fact]
    public async Task Hello()
    {
        var api = new TestApi();
        using var client = api.CreateClient();
        var response = await client.GetAsync("/hello");
        response.EnsureSuccessStatusCode();
        var responseContent = await response.Content.ReadAsStringAsync();
        Assert.Equal("world", responseContent);
    }
}

public class TestApi : WebApplicationFactory<Program>
{
    protected override void ConfigureWebHost(IWebHostBuilder builder)
    {
        builder.UseEnvironment("test"); // <-- In E2E test mode I want a different environment
    }
}

Describe the solution you'd like

The options ValidateScopes and ValidateOnBuild should be true by default when using WebApplicationFactory<TEntryPoint> which is designed for testing.

Additional context

This can easily be done manually via the following code. It's just unexpected that this isn't the default.

    protected override void ConfigureWebHost(IWebHostBuilder builder)
    {
        builder.UseEnvironment("test");
        builder.UseDefaultServiceProvider(options =>
        {
            options.ValidateScopes = true;
            options.ValidateOnBuild = true;
        });
    }
captainsafia commented 1 month ago

@andrewjsaid Thanks for filing this issue! The default behavior that you see here is a result of logic that is included in the WebApplicationBuilder's implemenetation. As you observed, it's gated behind an IsDevelopment check so modifying the environment name under test breaks this default behavior.

We're planning on doing a round of improvements for the integration testing area soon so I'm marking this as something we could potentially look into as part of the workstream.

For now, I'm sticking this in the backlog given there is a feasible workaround for the issue.