我们有几个.NET核心微服务/ API,我们希望做一些集成测试。因此,我们遵循教程,它工作很好,除了一种情况。
假设我有3个API,所以有3个"TestServer“实例,每个实例都有自己的HttpClient可连接!
我展示了创建TestServer的方式:
private TestServer SetupAPI<TStartup>(string path, string uri) where TStartup : class
{
string rootPath = Path.Join(_rootPath, "path");
var hostBuilder = WebHost.CreateDefaultBuilder()
.UseUrls(uri)
.UseIISIntegration()
//.ConfigureServices(services => services.AddSecurityHeaders())
.UseContentRoot(rootPath)
.UseEnvironment("Development")
.ConfigureAppConfiguration(cb =>
{
cb.AddJsonFile("appsettings.json", optional: false)
//.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
})
.UseStartup<TStartup>();
TestServer server = new TestServer(hostBuilder);
server.BaseAddress = new Uri(uri);
return server;
}我展示了如何创建HttpClient:
client = ArtistsServer.CreateClient();
client.BaseAddress = new Uri("http://localhost:5000");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));它工作得很好,但是当我尝试以这种方式创建一个新的HttpClient时,它失败了: HttpClient httpClient =新HttpClient();httpClient.BaseAddress =新Uri("http://localhost:5000");
真正的问题是,一些微服务通过这种方式创建自己的HttpClient,以便与其他API进行通信!它们是通过appsettings.json文件设置的,并试图连接到正常和真实的http服务器,而不是"TestServer“服务器!
你有办法解决这个问题吗?
谢谢
发布于 2019-11-08 14:22:13
这不是这么回事。集成测试是对组成一个应用程序的组件套件的测试。如果您正在测试Api1,那么您不需要旋转Api2和Api3的实例,而是对它们进行嘲弄,以便它们以已知和可预测的方式运行。如果使用实际实例,甚至测试实例,那么Api2中的失败可能会导致Api1测试失败,尽管Api1没有什么问题。
因此,要让Api1与Api2通信,就需要一个HttpClient来发出请求。HttpClient应该由IHttpClientFactory提供并注入到注册为类型化客户端的服务类中。在这个服务类上,您将添加与API调用对应的方法。为了便于测试,这个服务类应该实现一个接口,然后当您需要使用这个API时,您应该注入这个接口。看上去大致如下:
public interface IApi2Service
{
Task<Foo> GetFooByIdAsync(int id);
}
public class Api2Service : IApi2Service
{
private readonly HttpClient _client;
public Api2Service(HttpClient client)
{
_client = client;
}
public async Task<Foo> GetFooByIdAsync(int id)
{
// use _client to make the API call
}
}然后,在Startup.ConfigureServices中
services.AddHttpClient<IApi2Service, Api2Service>(c =>
{
c.BaseAddress = new Uri(Configuration["Api2BaseAddress"]);
});最后,在Api1中需要与Api2交互的类(可能是控制器)中,您需要:
public class SomeApi1Controller : ControllerBase
{
private readonly IApi2Service _api2Service;
public SomeApi1Controller(IApi2Service api2Service)
{
_api2Service = api2Service;
}
public async Task<IActionResult> SomeAction()
{
var foo = await _api2Service.GetFooByIdAsync(1);
}
}现在,在正确设置代码之后,只需在Api2Service的测试实现中分块,将GetFooByIdAsync方法存根出来,只返回一个测试Foo实例,而不是通过HttpClient对Api2进行实际调用。这样,您就可以确切地知道将返回什么,并且可以适当地设计您的测试,将不同类型的Foo实例适当地返回到您正在测试的内容中。
https://stackoverflow.com/questions/58764032
复制相似问题