Это проблема дизайна.Вы тесно связываете свой код с проблемами реализации, которые затрудняют тестирование вашего кода изолированно.
Сначала вам нужно реорганизовать создание клиента (проблема реализации) и явно внедрить его абстракцию в зависимый класс.
На самом деле нет необходимости внедрять проблемы инфраструктуры, такие как IConfiguration
, в ваши услуги.Это может восприниматься как запах кода, когда ваш класс не следует принципу явных зависимостей и вводит в заблуждение относительно того, от чего он на самом деле зависит.
При этом зависимый класс упрощается до
public class EmailQueueService : IEmailQueueService {
private readonly IAmazonSQS sqsClient
private readonly ILogger logger;
public EmailQueueService(IAmazonSQS sqsClient, ILogger<EmailQueueService> logger) {
this.sqsClient = sqsClient;
this.logger = logger;
}
public async Task<bool> AddAsync(ContactFormModel contactForm) {
var sendRequest = //...removed for clarity
var response = await sqsClient.SendMessageAsync(sendRequest);
return response.HttpStatusCode == System.Net.HttpStatusCode.OK;
}
}
Теперь перенесите создание клиента и его зависимость от параметров в корневой каталог композиции, который будет при запуске.
public Startup(IHostingEnvironment env) {
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
}
IConfiguration Configuration;
public void ConfigureServices(IServiceCollection services) {
// Add framework services.
services.AddMvc();
// Add AWS services
var options = Configuration.GetAWSOptions();
services.AddDefaultAWSOptions(options);
services.AddAWSService<IAmazonSQS>();
services.AddAWSService<IAmazonDynamoDB>();
services.AddSingleton<IEmailQueueService, EmailQueueService>();
//...omitted for brevity
}
Ссылка Настройка AWS SDKдля .NET с .NET Core
Это обеспечивает очистку кода, чтобы он мог запускаться локально, развернуто или при тестировании.
При тестировании вы можете создать клиент извнек тестируемому объекту и настройте его при необходимости специально для теста
public class EmailQueueServiceTests {
[Fact]
public async Task Should_AddAsync() {
// Arrange
var configuration = GetConfiguration();
IAmazonSQS client = configuration.GetAWSOptions().CreateServiceClient<IAmazonSQS>();
var subject = new EmailQueueService(client, Mock.Of<ILogger<EmailQueueService>>());
// Act
var result = await subject.AddAsync(ContactFormModelMock.GetNew());
// Assert
Assert.True(result);
}
static IConfiguration GetConfiguration() {
var builder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables();
return builder.Build();
}
}
IConfiguration
также может быть полностью смоделирован при желании или AWSOptions
, созданный вручную со значениями, необходимыми для тестирования.
Ваш выбор теперь увеличен и стал более гибким.