0

I have an ASP.NET Core 5 application running in IIS in production + I have integration tests for the application. And I have a problem that I do not know how to setup my HttpClient in integration tests to work both with "production" server (service running on my local IIS) and the TestServer.

This is how I am instantiating the HttpClient:

    private static HttpClient GetHttpClient(bool isProductionServer)
    {
      if (isProductionServer)
      {
        return new HttpClient {BaseAddress = new Uri("http://localhost/myservice/")};
      }

      var appFactory = new WebApplicationFactory<Startup>();
      var testClient = appFactory.CreateClient();
      return testClient;
    }

As explained in Why is HttpClient BaseAddress not working?, slash must be present at the end of BaseAddress and later, slash must not be present at the beginning of the relative URI.

But it seems that the test HttpClient created from WebApplicationFactory has the opposite requirement that slash must be present at the beginning of the relative URI. Since I am getting the relative URI from the same place, this is causing me problems. My tests are getting the httpClient instance from a base test class, and the tests should not care if they are executed against IIS or TestServer. Any idea how to make this work? Maybe some setting when creating the httpClient for the TestServer?

To further illustrate the problem, please take a look at the following two tests:

    [Test]
    public async Task TestRequestOnTestServer()
    {
      // works only for: "/api/v1/ping", but not for "api/v1/ping" - I get 404 response
      string route = ApiRoutes.V1.Health.PingGet;
      var client = GetHttpClient(false);
      var response = await client.GetAsync(route);
      Assert.That(response.IsSuccessStatusCode);
    }
    [Test]
    public async Task TestRequestOnProductionServer()
    {
      // works only for: "api/v1/ping", but not for "/api/v1/ping" - I get 404 response
      string route = ApiRoutes.V1.Health.PingGet;
      var client = GetHttpClient(true);
      var response = await client.GetAsync(route);
      Assert.That(response.IsSuccessStatusCode);
    }
Robert
  • 1
  • 4
  • do you have a custom `HttpClient` returned from `appFactory.CreateClient`? The custom client may have a custom behavior that changes the way it should work. – King King May 03 '21 at 07:34
  • 1
    Is there any reason why you're not using `IHttpClientFactory` when creating your `HttpClient`? – smoksnes May 03 '21 at 07:48
  • @Robert If you have found the answer for your own question then please leave a post and mark it as the answer. – Peter Csala May 03 '21 at 14:47
  • @PeterCsala: thanks for the hint - added the answer. @King King: standard `HttpClient` was used, seem the problem was in the controller. @smoksnes: Not sure what would be the benefit of using `IHttpClientFactory` inside the tests. None of the use cases described [here](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/http-requests) seem to apply to my use-case. – Robert May 03 '21 at 18:35

1 Answers1

0

Maybe HttpClient created from WebApplicationFactory does not have the behavior I assumed it has. Turns out the problem was in the Controller class which had the [Route("[controller]")] attribute, and the Ping method inside it had [Route(ApiRoutes.V1.Health.PingGet)].

In IIS ping was available at "/api/v1/ping" (not sure why), but when starting from VisualStudio swagger showed that the actual endpoint was "/Health/api/v1/ping" (which is wrong).

Removing the [Route("[controller]")] attribute fixed the problem and now both tests pass.

Robert
  • 1
  • 4