1

I have a controller endpoint that returns a RedirectRequest (status code 308). I am upgrading from ASP.NET Core 2.2 to 3.0, and will upgrade to 3.1 once the 3.0 upgrade is complete. I had an integration test that was working in .NET 2.2 that made a request to my redirected endpoint and confirmed it returns a 308. I also had a test that confirmed that my /swagger endpoint redirected to /swagger/index.html. It appears that both of these tests now are seeing the redirect response and automatically redirecting. My /swagger test returns a 200 with the contents of /swagger/index.html. My redirect to an external url that does not exist returns a 404 (I am using the test HttpClient so real sites would not load).

Controller:

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace MyService.Controllers
{
    [ApiController]
    public class MyController : ControllerBase
    {
        [HttpGet]
        [Route("myroute")]
        [ProducesResponseType(308)]
        [AllowAnonymous]
        public IActionResult MyEndpoint()
        {
            return new RedirectResult("https://google.com/", true, true);
        }
    }
}

My tests:

using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Reflection;
using System.Threading.Tasks;
using Xunit;

namespace MyService.UnitTests.ControllerTests
{
    public class MyControllerTests : IClassFixture<ControllerTestWebApplicationFactory<Startup>>
    {
        private readonly ControllerTestWebApplicationFactory<Startup> _factory;

        public MyControllerTests(ControllerTestWebApplicationFactory<Startup> factory)
        {
            _factory = factory;
        }

        private HttpClient GetHttpClient()
        {
            return _factory.CreateClient();
        }

        [Fact]
        public async Task RedirectTest()
        {
            using (var client = GetHttpClient())
            {
                var request = new HttpRequestMessage(HttpMethod.Get, "/myroute");
                var response = await client.SendAsync(request);

                await response.AssertStatus(StatusCodes.Status308PermanentRedirect);
                var res = await response.Content.ReadAsStringAsync();
                Assert.Empty(res);
                Assert.Equal("https://google.com", response.Headers.Location.AbsoluteUri);
            }
        }

        [Fact]
        public async Task Swagger()
        {
            using (var client = GetHttpClient())
            {
                var request = new HttpRequestMessage(HttpMethod.Get, "/swagger");
                var response = await client.SendAsync(request);

                // This code passes in 2.2
                // await response.AssertStatus(StatusCodes.Status308);
                // var res = await response.Content.ReadAsStringAsync();
                // Assert.Empty(res);
                // Assert.Equal("swagger/index.html", response.Headers?.Location.OriginalString);

                // This code passes in 3.0
                await response.AssertStatus(StatusCodes.Status200OK);
                var res = await response.Content.ReadAsStringAsync();
                Assert.StartsWith("<!-- HTML for static distribution bundle", res);
                Assert.Null(response.Headers?.Location);
            }
        }
    }
}

It looks like the tests are resolving the 30x response to the final location, but I want to prevent this automatic redirect so that I can test that the redirect is in place when I expect. Especially with the myroute endpoint that resolves to an external endpoint, since this creates a 404 in the test, I would not be able to tell the difference between the endpoint being deleted entirely and the redirect working as expected.

4

2 Answers 2

6

This is a duplicate of a question that was not linked by others: How do I test an https redirect in ASP.NET Core?

Basically, I needed to change:


        private HttpClient GetHttpClient()
        {
            return _factory.CreateClient();
        }

to

        protected HttpClient GetHttpClient()
        {
            var opts = new WebApplicationFactoryClientOptions
            {
                AllowAutoRedirect = false
            };
            return _factory.CreateClient(opts);
        }
Sign up to request clarification or add additional context in comments.

Comments

-1

When you build the HttpClient, you can pass an HttpClientHandler with AllowAutoRedirect set to true to it. Then it won't automatically redirect.

var httpClient = new HttpClient(new HttpClientHandler{ AllowAutoRedirect = true });

Edit: Of course you'll have to integrate this into your factory somehow.

2 Comments

Turns out this is a duplicate questions. Can't say I'm surprised.
Just for others who might read this answer, if the system under test has request redirection enabled, setting AllowAutoRedirect to true allows HTTP request redirection on the system under test so you would receive the actual response from the endpoint being tested. Otherwise, setting this to false will make you receive a redirect response (307 or 308).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.