对 .Net core 3.1 后台服务进行单元测试时,无法解析 IConfiguration
While Unit Testing a .Net core 3.1 Background Service, unable to resolve IConfiguration
我正在尝试为 BackgroundService Worker.cs
编写单元测试用例。我已阅读
但我仍然收到
的错误
"Unable to resolve service for type 'Microsoft.Extensions.Configuration.IConfiguration' while attempting to activate 'AutoClueArchiver.Worker'.
public WorkerTests()
{
_config = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", true, true)
.AddJsonFile("appsettings.Development.json", true, true)
.AddJsonFile("appsettings.local.json", true, true)
.AddJsonFile("\\charon.cmiprog.com\devinet\Configuration\" + "ApiEndpoints.json", false, true)
.AddJsonFile("ApiEndpoints.local.json", true, true)
.AddJsonFile("\\charon.cmiprog.com\devinet\Configuration\" + "Kafka.json", false, true)
.AddEnvironmentVariables().Build();
_mockedKafkaTopicConsumerManager =new Mock<IKafkaTopicConsumerManager>();
_mockedMessageProcessor=new Mock<IMessageProcessingCapable>();
}
[Fact]
public async Task ExecuteAsync_Test()
{
IServiceCollection services=new ServiceCollection();
services.AddSingleton<IConfigEntriesClientService, ConfigEntriesClientServiceInjectable>();
services.AddSingleton(typeof(IProducer), s => new KafkaProducer(s.GetRequiredService<IProducer<string, string>>(), s.GetRequiredService<IConfiguration>().GetValue<string>("Shared:Kafka:TopicSuffix")));
services.AddSingleton(typeof(IProducer<string, string>), c => new ProducerBuilder<string, string>(KafkaConfigs(c)).Build());
services.AddHttpClient();
services.AddScoped<IPolicyApiClient, PolicyApiClient>();
services.AddTransient<IFilterMessages, MessageFilter>();
services.AddTransient<IArchiveAutoClues, Archiver>();
services.AddTransient<IFileSystem, FileSystem>();
services.AddTransient<ISaveDocument, DocumentManager>();
services.AddTransient<IKafkaTopicConsumerManager, KafkaTopicConsumerManager>();
services.AddTransient<IMessageProcessingCapable, ConsumerInitializer>();
services.AddTransient<Consumer>();
services.AddTransient<IExceptionPublisher, ExceptionPublisher>();
services.AddTransient<IHttpContextAccessor, HttpContextAccessor>();
services.AddScoped(sp => new HttpClientHandler { AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate });
services.AddHttpClient<IBaseApiClient, BaseApiClient>().ConfigurePrimaryHttpMessageHandler(
sp => new HttpClientHandler { AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate }
);
var worker=services.AddHostedService<Worker>();
var serviceProvider=services.BuildServiceProvider();
var backgroundService = serviceProvider.GetService<IHostedService>() as Worker;
await backgroundService?.StartAsync(CancellationToken.None);
await Task.Delay(1000);
await backgroundService?.StopAsync(CancellationToken.None);
//await backgroundService.ExecuteAsync(new CancellationToken());
//Any way to access ExecuteAsync here since I get protection level error as
//ExecuteAsync is protected
_mockedKafkaTopicConsumerManager.Verify(c=>c.StartConsumption
(It.IsAny<CancellationToken>(),
_mockedMessageProcessor.Object,
It.IsAny<string>(),
It.IsAny<string>(),
It.IsAny<List<string>>(),
It.IsAny<string>(),
It.IsAny<int>()),Times.Once);
}
我没有看到您将 IConfiguration
添加到服务集合的位置。您在构造函数中构建一个但不将其添加到测试中的服务集合。
[Fact]
public async Task ExecuteAsync_Test() {
IServiceCollection services = new ServiceCollection();
services.AddSingleton<IConfiguration>(_config);
//...
如果您使用 xUnit dependecy nuget,获取 IConfiguration 的最佳方法是:
在 Stratup.cs
public void ConfigureHost(IHostBuilder hostBuilder) =>
hostBuilder.ConfigureAppConfiguration(lb => lb.AddJsonFile("appsettings.json", false, true))
.UseServiceProviderFactory(new AutofacServiceProviderFactory());
然后在你的构造函数中测试 class:
readonly IConfiguration _configuration;
public WorkerTestUnit(IConfiguration configuration)
=>
_configuration = configuration;
终于在你的测试中:
[Fact]
public async Task ExecuteAsync_Test()
{
.....
services.AddSingleton<IConfiguration>(_configuration);
....
}
我正在尝试为 BackgroundService Worker.cs
编写单元测试用例。我已阅读
但我仍然收到
的错误"Unable to resolve service for type 'Microsoft.Extensions.Configuration.IConfiguration' while attempting to activate 'AutoClueArchiver.Worker'.
public WorkerTests()
{
_config = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", true, true)
.AddJsonFile("appsettings.Development.json", true, true)
.AddJsonFile("appsettings.local.json", true, true)
.AddJsonFile("\\charon.cmiprog.com\devinet\Configuration\" + "ApiEndpoints.json", false, true)
.AddJsonFile("ApiEndpoints.local.json", true, true)
.AddJsonFile("\\charon.cmiprog.com\devinet\Configuration\" + "Kafka.json", false, true)
.AddEnvironmentVariables().Build();
_mockedKafkaTopicConsumerManager =new Mock<IKafkaTopicConsumerManager>();
_mockedMessageProcessor=new Mock<IMessageProcessingCapable>();
}
[Fact]
public async Task ExecuteAsync_Test()
{
IServiceCollection services=new ServiceCollection();
services.AddSingleton<IConfigEntriesClientService, ConfigEntriesClientServiceInjectable>();
services.AddSingleton(typeof(IProducer), s => new KafkaProducer(s.GetRequiredService<IProducer<string, string>>(), s.GetRequiredService<IConfiguration>().GetValue<string>("Shared:Kafka:TopicSuffix")));
services.AddSingleton(typeof(IProducer<string, string>), c => new ProducerBuilder<string, string>(KafkaConfigs(c)).Build());
services.AddHttpClient();
services.AddScoped<IPolicyApiClient, PolicyApiClient>();
services.AddTransient<IFilterMessages, MessageFilter>();
services.AddTransient<IArchiveAutoClues, Archiver>();
services.AddTransient<IFileSystem, FileSystem>();
services.AddTransient<ISaveDocument, DocumentManager>();
services.AddTransient<IKafkaTopicConsumerManager, KafkaTopicConsumerManager>();
services.AddTransient<IMessageProcessingCapable, ConsumerInitializer>();
services.AddTransient<Consumer>();
services.AddTransient<IExceptionPublisher, ExceptionPublisher>();
services.AddTransient<IHttpContextAccessor, HttpContextAccessor>();
services.AddScoped(sp => new HttpClientHandler { AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate });
services.AddHttpClient<IBaseApiClient, BaseApiClient>().ConfigurePrimaryHttpMessageHandler(
sp => new HttpClientHandler { AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate }
);
var worker=services.AddHostedService<Worker>();
var serviceProvider=services.BuildServiceProvider();
var backgroundService = serviceProvider.GetService<IHostedService>() as Worker;
await backgroundService?.StartAsync(CancellationToken.None);
await Task.Delay(1000);
await backgroundService?.StopAsync(CancellationToken.None);
//await backgroundService.ExecuteAsync(new CancellationToken());
//Any way to access ExecuteAsync here since I get protection level error as
//ExecuteAsync is protected
_mockedKafkaTopicConsumerManager.Verify(c=>c.StartConsumption
(It.IsAny<CancellationToken>(),
_mockedMessageProcessor.Object,
It.IsAny<string>(),
It.IsAny<string>(),
It.IsAny<List<string>>(),
It.IsAny<string>(),
It.IsAny<int>()),Times.Once);
}
我没有看到您将 IConfiguration
添加到服务集合的位置。您在构造函数中构建一个但不将其添加到测试中的服务集合。
[Fact]
public async Task ExecuteAsync_Test() {
IServiceCollection services = new ServiceCollection();
services.AddSingleton<IConfiguration>(_config);
//...
如果您使用 xUnit dependecy nuget,获取 IConfiguration 的最佳方法是:
在 Stratup.cs
public void ConfigureHost(IHostBuilder hostBuilder) =>
hostBuilder.ConfigureAppConfiguration(lb => lb.AddJsonFile("appsettings.json", false, true))
.UseServiceProviderFactory(new AutofacServiceProviderFactory());
然后在你的构造函数中测试 class:
readonly IConfiguration _configuration;
public WorkerTestUnit(IConfiguration configuration)
=>
_configuration = configuration;
终于在你的测试中:
[Fact]
public async Task ExecuteAsync_Test()
{
.....
services.AddSingleton<IConfiguration>(_configuration);
....
}