在开发过程中"mocking"类



我遇到了这个问题,我需要进行外部API调用,但是在生产中我必须为API调用使用证书,而在开发中我并不真正需要证书。我想知道如何实现一个解决方案,在那里我可以有生产代码和开发代码之间的分离,所以我不必注释出来的部分,可能忘记改变它。任何提示将不胜感激!

public async Task<GetPersonResponse> PostPerson(PersonDto dto) 
{
try {
var httpHandler = new HttpClientHandler();
var certificate = new X509Certificate2(
Path.Join(_certOptions.Path, _certOptions.Name),
_certOptions.Password, 
X509KeyStorageFlags.MachineKeySet);
httpHandler.ClientCertificates.Add(certificate);
var client = new HttpClient(httpHandler);
var soapRequest = GenerateRequest(dto);
var request = new HttpRequestMessage() {
RequestUri = new Uri(_options.Value.URL),
Method = HttpMethod.Post,
Content = new StringContent(soapRequest.ToString(), Encoding.UTF8, "text/xml"),
};
var response = await client.SendAsync(request);
}
}

有两件事可以帮上忙。首先,你应该看看HttpClientFactory,它可以让你传入httpclient并正确配置它-现在你正在泄漏套接字与你所显示的代码。

对于如何让代码处理基于环境变化的行为这一更普遍的问题,有两种非常常见的方法。

首先是将行为抽象为每个环境的一个接口和实现。然后根据环境更改实现。在你的web应用中,你会注册一个基于运行时环境的特定实现。然后你的控制器将在它的构造函数中获取接口。

第二种方法是传入一个包含运行时信息的配置元素,然后有条件地执行代码。在这种情况下,控制器将接受构造函数中的configuration元素。

我会避免使用条件编译,因为它更难测试。

您可以像这样使用条件预处理器#if #else #endif:

#if DEBUG
Console.WriteLine("Code will executed only in a debug configuration");
#else
Console.WriteLine("Executed if not in a debug configuration");
#endif

您的代码中已经条件:

_options.Value.URL

创建_options.Value.UseCertificate并在证书代码周围放置if会有问题吗?

另一种方法是使用配置设置并使用它来限制证书的使用

dev配置:

<add key="UseCertificate" value="False"/>

prod配置:

<add key="UseCertificate" value="True"/>

条件:

ConfigurationManager.AppSettings["UseCertificate"]