gpt4 book ai didi

c# - AWS .NET Core单元测试加载非默认配置文件

转载 作者:行者123 更新时间:2023-12-02 04:21:36 24 4
gpt4 key购买 nike

对于开发,我有许多 AWS 配置文件,我使用 appsettings.json 中的 AWS 配置文件部分来定义我要使用的配置文件:

"AWS": {
"Profile": "CorpAccount",
"Region": "us-east-1"
}

由于这不是默认配置文件,因此在调试和运行单元测试 (xunit) 时,我需要上下文来使用命名配置文件。我想知道配置配置文件的最佳实践是什么。

这是一个展示三种方法的类(其中两种在本地工作):

public class EmailQueueService : IEmailQueueService
{
private IConfiguration _configuration;
private readonly ILogger _logger;

public EmailQueueService(IConfiguration configuration, ILogger<EmailQueueService> logger)
{
_configuration = configuration;
_logger = logger;
}

public async Task<bool> Add1Async(ContactFormModel contactForm)
{
var sqsClient = new AmazonSQSClient();

var sendRequest = // removed for clarity

var response = await sqsClient.SendMessageAsync(sendRequest);

return response.HttpStatusCode == System.Net.HttpStatusCode.OK;
}

public async Task<bool> Add2Async(ContactFormModel contactForm)
{
var sqsClient = _configuration.GetAWSOptions().CreateServiceClient<IAmazonSQS>();

var sendRequest = // removed for clarity

var response = await sqsClient.SendMessageAsync(sendRequest);

return response.HttpStatusCode == System.Net.HttpStatusCode.OK;
}

public async Task<bool> Add3Async(ContactFormModel contactForm)
{
var sqsClient = new AmazonSQSClient(credentials: Common.Credentials(_configuration));

var sendRequest = // removed for clarity

var response = await sqsClient.SendMessageAsync(sendRequest);

return response.HttpStatusCode == System.Net.HttpStatusCode.OK;
}

public AWSCredentials Credentials(IConfiguration config)
{
var chain = new CredentialProfileStoreChain();

if (!chain.TryGetAWSCredentials(config.GetAWSOptions().Profile, out AWSCredentials awsCredentials))
{
throw new Exception("Profile not found.");
}

return awsCredentials;
}
}

结果:

  • Add1Async 在本地失败,因为它使用默认配置文件而不是“CorpAccount”。
  • Add2Async 在本地工作,但这似乎是创建新实例的奇怪方法。
  • Add3Async 在本地工作,但部署时可能会失败,因为 config.GetAWSOptions().Profile 不存在于本地环境之外。

为了完整起见,这是我调用它的单元测试:

[Fact]
public async void AddAsyncTest()
{
// Arrange
var configuration = TestConfigure.Getconfiguration();

var service = new EmailQueueService(configuration, Mock.Of<ILogger<EmailQueueService>>());

// Act
var result = await service.AddAsync(ContactFormModelMock.GetNew());

// Assert
Assert.True(result);
}

public static IConfiguration Getconfiguration()
{
var builder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables();

return builder.Build();
}

最佳答案

这是一个设计问题。您将代码与实现问题紧密耦合,这使得单独测试代码变得困难。

您首先需要重构客户端的创建(实现问题)并将其抽象显式注入(inject)到依赖类中。

确实没有必要将像 IConfiguration 这样的框架问题注入(inject)到您的服务中。这可以被视为代码异味,您的类没有遵循 Explicit Dependencies Principle并且误导了它实际依赖的内容。

这样,依赖类就简化为

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
}

引用Configuring the AWS SDK for .NET with .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

您的选择现在更多且更加灵活。

关于c# - AWS .NET Core单元测试加载非默认配置文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55974785/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com