alba icon indicating copy to clipboard operation
alba copied to clipboard

Inconsistent behavior when using AlbaHost.For

Open firedog opened this issue 3 years ago • 1 comments

.NET 6, Alba 7.2.1

Using the following test...

public class Tests
{
    [Fact]
    public async Task Response_Is_Hello_World()
    {
        await using var host = await AlbaHost.For<Program>();

        await host.Scenario(s =>
        {
            s.Get.Url("/");
            s.ContentShouldBe("Hello, World!");
        });
    }
}

..when SUT is...

public class Program
{
    public static void Main(string[] args)
    {
        throw new ApplicationException("Main was called!");
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

public class Startup
{
    public void Configure(IApplicationBuilder app)
    {
        app.UseRouting();
        app.UseEndpoints(endpoints =>
        {
            endpoints.Map("/", () => "Hello, World!");
        });
    }
}

...leads to a successful test! (i.e. Main was never called)

Renaming the CreateHostBuilder method to CreateHostBuilder2 and thus using SUT as ...

public class Program
{
    public static void Main(string[] args)
    {
        throw new ApplicationException("Main was called!");
        CreateHostBuilder2(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder2(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

public class Startup
{
    public void Configure(IApplicationBuilder app)
    {
        app.UseRouting();
        app.UseEndpoints(endpoints =>
        {
            endpoints.Map("/", () => "Hello, World!");
        });
    }
}

...leads to a failed test as the exception is thrown. (i.e. Main was called)

I guess this has to do with the logic in EnsureServer() (as described by Andrew Lock in https://andrewlock.net/exploring-dotnet-6-part-6-supporting-integration-tests-with-webapplicationfactory-in-dotnet-6/) that looks for older ways of doing things and uses the ASP.NET Core 3.x/5 convention when it finds a method named CreateHostBuilder.

Don't know if there's something to do about this or if just should be documented somewhere?

firedog avatar Dec 05 '22 14:12 firedog

This aligns with the expected behavior of the internal resolver, it'll search for variations of CreateHostBuilder, and if it's not found, kick off the entry-point to check if it's a WebApplicationBuilder project. I expect most people using .NET 6 and newer will be using WebApplicationBuilder, but I'll add a note that the application needs to conform with default template conventions if using CreateHostBuilder.

Hawxy avatar Dec 06 '22 02:12 Hawxy