AspNet Core Integration test, pass arguments to WebApplicationFactory
Asked Answered
M

4

9

I have application that designed to be standalone aspnet core webapi self host executable.

To start the executable a config file path MUST be pass as command line argument (e.g. MyServer.exe --config "path-to-config-file")

I would like to test it via integration tests (Following this page: https://learn.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-2.1)

My question - how does command line arguments are passed to WebApplicationFactory?

Thank you

Maurya answered 9/7, 2018 at 9:6 Comment(0)
S
10

Command-line arguments are handled by the command-line configuration provider. In other words, the end result is that you simply end up with those values in your configuration root, and that's where you'd access them from later to utilize them. Given that, you can simply use any means of configuration in test to provide the same value, or even just write directly to the configuration.

If you haven't already, you should subclass your Startup class specifically for testing, i.e. something like:

public class TestStartup : Startup
{
    public TestStartup(IConfiguration configuration)
        : base(configuration)
    {

    }
}

Then, inside your TestStartup constructor, you can set the appropriate value in your configuration:

configuration["config"] = "path-to-config-file";

Just bear in mind that the type param to WebApplicationFactory is simply used to determine the "entry point", i.e. which Program the test host is going to run to bootstrap itself. As a result, you should continue to use WebApplicationFactory<Startup>, but then configure your test host to use your TestStartup instead:

public MyTests(WebApplicationFactory<Startup> factory)
{
    factory = factory.WithWebHostBuilder(builder => builder.UseStartup<TestStartup>());
}
Snashall answered 9/7, 2018 at 12:59 Comment(1)
and then how to ovverdie ConfigureServices from base startup not to change the base startup ?Cipango
H
6

I am using .NET 6.0 and this is how I can achieve passing command-line arguments into my Program.Main(string[] args) from my custom WebApplicationFactory<TStartup>.

public class CustomWebApplicationFactory<TStartup>
    : WebApplicationFactory<TStartup> where TStartup : class
{
    protected override void ConfigureWebHost(IWebHostBuilder builder)
    {
        // Notice there is no `--` prefix in "config"
        builder.UseSetting("config", "path-to-config-file");

        // other stuff as usual
    }
}

Afterwards, put a debugger breakpoint in your Program.cs file Main(string[] args) and you will see your "config" command-line parameter come into args as "--config=path-toconfig-file".

Hoary answered 14/9, 2022 at 18:36 Comment(0)
C
2

Shortly, IWebHostBuilder.UseSetting helps to add or replace a setting in the configuration: Microsoft Learn. How to use it:

In Program.cs:

public static void Main(string[] args)
{
    var builder = WebApplication.CreateBuilder(args);
    //...
    var app = builder.Build();
    //...
}

In unit/integration tests:

var application = new WebApplicationFactory<Program>()
        .WithWebHostBuilder(builder =>
        {
            builder.UseSetting("param01", "---");
            builder.ConfigureServices((context, services) =>
            {
                //some reconfiguration of external dependencies
            });
        });
Contemplation answered 9/1, 2023 at 6:10 Comment(0)
I
0

To pass values directly to CommandLineConfigurationProvider:

public class CustomFactory : WebApplicationFactory<Startup>
{
    protected override void ConfigureWebHost(IWebHostBuilder builder)
    {
        builder.ConfigureAppConfiguration(configurationBuilder =>
        {
            configurationBuilder.AddCommandLine(new string[] { "--config \"path-to-config-file\"" });
        });
        base.ConfigureWebHost(builder);
    }
}
Inkberry answered 16/3, 2022 at 11:6 Comment(2)
This technique doesn't work because command-line arguments populated inside ConfigureAppConfiguration doesn't get passed into Program.Main. They will only get passed if it is added to the HostConfiguration. You can verify my comment by putting a debugger breakpoint inside Program.Main(string[] args). You will see args only contain "--contentRoot" and "--environment=Development" and "--applicationName=YourAppName". Your "--config=path-to-config-file" will not be in there.Hoary
I wrote answer, when I was using .NET5 (Startup and Program classes were separated). Indeed in .NET6 we can't see custom argument in args variable. However it's still passed to CommandLineConfigurationProvider (we can verify that in builder.Configuration non-public members).Inkberry

© 2022 - 2024 — McMap. All rights reserved.