【问题标题】:Net Core - Integration test - TestServer - real http connectionNet Core - 集成测试 - TestServer - 真实的http连接
【发布时间】:2020-03-04 22:29:31
【问题描述】:

我们有几个 .NET Core 微服务/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 = new HttpClient(); httpClient.BaseAddress = new Uri("http://localhost:5000");

真正的问题是,一些微服务以这种方式创建自己的 HttpClient 以便与其他 API 通信!它们是通过 appsettings.json 文件设置的,并尝试连接到正常且真实的 http 服务器,而不是“TestServer”!

你有什么办法解决这个问题吗?

谢谢

【问题讨论】:

    标签: c# asp.net-core asp.net-web-api integration-testing


    【解决方案1】:

    这不是它的工作原理。集成测试是对组成单个应用程序的组件套件的测试。如果您正在测试 Api1,则不会启动 Api2 和 Api3 的实例;你嘲笑那些,让他们以一种已知和可预测的方式行事。如果您使用真实实例,即使是 test 实例,那么 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 实例。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-07-14
      • 1970-01-01
      • 2020-07-21
      • 2020-07-08
      • 1970-01-01
      • 2021-07-05
      • 1970-01-01
      • 2020-08-18
      相关资源
      最近更新 更多