在哪里创建 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 使用 IHostBuilder
的 CreateHostBuilder
.
的 .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);
}
}
我采用了一个仅由 class 库和单元测试项目组成的遗留 .NET Framework 应用程序,并将它们全部转换为 .NET Core 3.1。
我似乎无法执行或 bootstrap 使用 IHostBuilder
的 CreateHostBuilder
.
当我调试我的任何单元测试时,它停止执行并且我得到这个错误:
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);
}
}