AspNet Core集成测试,向WebApplicationFactory传递参数

5
我有一个应用程序,旨在作为独立的aspnet core webapi自承载可执行文件运行。
启动该可执行文件时,必须传递配置文件路径作为命令行参数(例如:MyServer.exe --config "path-to-config-file")。
我想通过集成测试来测试它(参考这个页面:https://learn.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-2.1)。
我的问题是:如何将命令行参数传递给WebApplicationFactory
谢谢
4个回答

9
命令行参数由命令行配置提供程序处理。换句话说,最终结果就是你只需在配置根中得到这些值,然后以后就可以从那里访问它们来利用它们。鉴于此,您可以在测试中使用任何配置手段来提供相同的值,甚至只需直接编写到配置中。
如果您还没有这样做,您应该为测试专门子类化您的Startup类,例如:
public class TestStartup : Startup
{
    public TestStartup(IConfiguration configuration)
        : base(configuration)
    {

    }
}

然后,在你的TestStartup构造函数内,你可以在你的配置中设置相应的值:

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

请记住,WebApplicationFactory 的类型参数仅用于确定“入口点”,即测试主机将运行哪个 Program 来引导自身。因此,您应继续使用 WebApplicationFactory<Startup>,但要配置您的测试主机使用您的 TestStartup

public MyTests(WebApplicationFactory<Startup> factory)
{
    factory = factory.WithWebHostBuilder(builder => builder.UseStartup<TestStartup>());
}

1
然后如何从基础启动中覆盖ConfigureServices以不更改基础启动? - kosnkov

4

我正在使用.NET 6.0,这是我如何通过我的自定义WebApplicationFactory<TStartup>将命令行参数传递给Program.Main(string[] args)的方法。

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
    }
}

接下来,在您的Program.cs文件的Main(string[] args)函数中设置一个调试器断点,您将看到您的“config”命令行参数作为"--config=path-to-config-file"传入args数组中。


2

简单来说,IWebHostBuilder.UseSetting 可以帮助添加或替换配置中的设置:Microsoft Learn。如何使用它:

在 Program.cs 中:

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

在单元/集成测试中:
var application = new WebApplicationFactory<Program>()
        .WithWebHostBuilder(builder =>
        {
            builder.UseSetting("param01", "---");
            builder.ConfigureServices((context, services) =>
            {
                //some reconfiguration of external dependencies
            });
        });

1

直接将值传递给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);
    }
}

这种技术不起作用,因为在ConfigureAppConfiguration中填充的命令行参数不会传递到Program.Main。只有将其添加到Host配置中才会传递。您可以通过在Program.Main(string[] args)中设置调试器断点来验证我的评论。您将看到args仅包含“--contentRoot”、“--environment=Development”和“--applicationName=YourAppName”。您的“--config=path-to-config-file”将不会出现在其中。 - stun
我写这篇答案时使用的是.NET5(Startup和Program类被分开)。实际上,在.NET6中,我们无法在args变量中看到自定义参数。但是它仍然传递给了CommandLineConfigurationProvider(我们可以在builder.Configuration的非公共成员中验证)。 - Natan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接