在哪里创建 HostBuilder 并避免 'The following constructor parameters did not have matching fixture data'

Where to create HostBuilder and avoid 'The following constructor parameters did not have matching fixture data'

我采用了一个仅由 class 库和单元测试项目组成的遗留 .NET Framework 应用程序,并将它们全部转换为 .NET Core 3.1。

我似乎无法执行或 bootstrap 使用 IHostBuilderCreateHostBuilder.

的 .NET 核心方法进行单元测试

当我调试我的任何单元测试时,它停止执行并且我得到这个错误:

The following constructor parameters did not have matching fixture data: IOptions`1 appConfig, IServiceX serviceX, ITemplateEngine templateEngine Exception doesn't have a stacktrace

样本单元测试:

public class TemplateGenerationTests : BaseTest
{
    private readonly AppConfiguration appConfig;
    private readonly IServiceX serviceX;
    private readonly ITemplateEngine templateEngine;

    public TemplateGenerationTests(IOptions<AppConfiguration> appConfig, IServiceX serviceX, ITemplateEngine templateEngine)
    {
        this.appConfig = appConfig.Value;
        this.serviceX = serviceX;
        this.templateEngine = templateEngine;
    }

    [Fact]
    public void SomeTestIhave()
    {
        //removed for brevity
        serviceX.DoWork(appConfig.SomeAppProp);
        

        Assert.NotNull(result);
        Assert.NotEmpty(result);
    }
}

Base class(我感觉这是创建主机构建器的错误方式):

public class BaseTest
{
    public BaseTest()
    {
        var builder = CreateHostBuilder();
        Task.Run(() => builder.RunConsoleAsync());
    }

    public static IHostBuilder CreateHostBuilder(string[] args = null) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
                config.AddJsonFile("appsettings.json", optional: true);
                config.AddEnvironmentVariables();

                if (args != null)
                {
                    config.AddCommandLine(args);
                }
            })
            .ConfigureServices((hostContext, services) =>
            {
                services.AddOptions();
                services.Configure<AppConfiguration>(hostContext.Configuration.GetSection("AppConfiguration"));
                
                services.AddTransient<IServiceX, ServiceX>();
                services.AddTransient<ITemplateEngine, TemplateEngine>();
                
                //removed for brevity..
            })
            .ConfigureLogging((hostingContext, logging) =>
            {
                logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
                logging.AddConsole();
            });
}

理想情况下,我正在寻找可以设置 HostBuilder 的单点,即在控制台或 API .NET 项目中,这将在 Main 方法中Program class.

通过小的修改,您可以摆脱将服务注入 TemplateGenerationTests class:

BaseTest class:

public class BaseTest
{
    public BaseTest()
    {
        TestHost = CreateHostBuilder().Build();
        Task.Run(() => TestHost.RunAsync());
    }

    public IHost TestHost { get; }

    public static IHostBuilder CreateHostBuilder(string[] args = null) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
                config.AddJsonFile("appsettings.json", optional: true);
                config.AddEnvironmentVariables();

                if (args != null)
                {
                    config.AddCommandLine(args);
                }
            })
            .ConfigureServices((hostContext, services) =>
            {
                services.AddOptions();
                services.Configure<AppConfiguration>(hostContext.Configuration.GetSection("AppConfiguration"));

                services.AddTransient<IServiceX, ServiceX>();
                services.AddTransient<ITemplateEngine, TemplateEngine>();

                //removed for brevity..
            })
            .ConfigureLogging((hostingContext, logging) =>
            {
                logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
                logging.AddConsole();
            });
}

TemplateGenerationTests class:

public class TemplateGenerationTests : IClassFixture<BaseTest>
{
    private readonly IHost _host;

    public TemplateGenerationTests(BaseTest baseTest)
    {
        _host = baseTest.TestHost;
    }

    [Fact]
    public void SomeTestIhave()
    {
        // Arrange
        var serviceX = _host.Services.GetService<IServiceX>();
        var appConfig = _host.Services.GetService<AppConfiguration>();

        // Act
        var result = serviceX.DoWork(appConfig.SomeAppProp);

        // Assert
        Assert.NotNull(serviceX);
        Assert.NotEmpty(result);
    }
}