HTTP-клиент не перенаправляет в интеграционных тестах - PullRequest
1 голос
/ 12 февраля 2020

Я настроил интеграционный тест:

public class IntegrationTests
{
    private readonly TestServer _server;
    private readonly HttpClient _client;

    public IntegrationTests()
    {
        _server = new TestServer(WebHost.CreateDefaultBuilder().UseEnvironment("Development").UseStartup<Startup>())
        {
            PreserveExecutionContext = true,
        };
        _client = _server.CreateClient();
    }

    [Test]
    public async Task RunARoute()
    {
        var response = await _client.GetAsync("/foo");

        Check.That(response.IsSuccessStatusCode).IsTrue();
    }
}

Запуск:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews()
        .AddApplicationPart(typeof(HomeController).Assembly)
        .AddControllersAsServices()
        .SetCompatibilityVersion(CompatibilityVersion.Version_3_0);

    services
        .ConfigureAll(Configuration) // Add the configuration sections
        .AddAllServices() // DI
        // Other:
        .AddAutoMapperProfiles(AutoMapperConfiguration.LoadConfig)
        .AddCacheHelper(e => {})
        .AddSession(opt => opt.Cookie.IsEssential = true);
}

public void Configure(IApplicationBuilder app)
{
    app.UseHttpsRedirection()
        .UseStaticFiles()
        .UseRouting()
        .UseCookiePolicy()
        .UseSession()
        .UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                "default",
                "{controller=Home}/{action=Index}/{id?}");
        });
}

В методе теста вызываемый мной маршрут перенаправляет на другой маршрут: return RedirectToAction(nameof(Bar)). Я хотел бы проверить, что страница корректно возвращается методом Bar, но, к сожалению, HttpClient не перенаправляет вызов: мой тест завершается неудачно с кодом 302.

I ' В Inte rnet мы читали, что эта проблема обычно возникает при попытке перенаправления с HTTPS-маршрута на HTTP-маршрут, но AFAIK здесь не так, поскольку тестовый сервер создает клиента с базовым URL-адресом. http://localhost/, а URL перенаправления является относительным (поэтому протокол не указан).

Как я могу убедиться, что клиент перенаправляет вызовы?

1 Ответ

2 голосов
/ 12 февраля 2020

То есть по замыслу. Если вы проверите исходный код TestServer

public HttpMessageHandler CreateHandler()
{
    var pathBase = BaseAddress == null ? PathString.Empty : PathString.FromUriComponent(BaseAddress);
    return new ClientHandler(pathBase, Application) { AllowSynchronousIO = AllowSynchronousIO, PreserveExecutionContext = PreserveExecutionContext };
}

public HttpClient CreateClient()
{
    return new HttpClient(CreateHandler()) { BaseAddress = BaseAddress };
}

, вы увидите, что он не включает функцию автоматического перенаправления, которая на самом деле является частью HttpClientHandler, обычно используемой по умолчанию HttpClient.

TestServer, однако, использует пользовательский обработчик, который не перенаправляет автоматически при создании HttpClient. Вам потребуется доступ к обработчику, который вы не можете получить, поскольку тестовый сервер создает клиента внутри себя.

Поэтому описанный код ведет себя так, как ожидалось.

Статус ответа HTTP код 302 Найденный является распространенным способом выполнения перенаправления.

Проверьте заголовок ответа, чтобы убедиться, что заголовок местоположения перенаправления находится на желаемом URL-адресе для подтверждения ожидаемого поведения.

Вы можете также попробуйте вручную вызвать перенаправленный URL-адрес, чтобы убедиться, что он вернет код состояния ответа HTTP 200 OK

[Test]
public async Task RunARoute_Should_Redirect() {        
    _server.PreserveExecutionContext = true;
    var client = _server.CreateClient();
    var response = await _client.GetAsync("/foo");

    Check.That(response.StatusCode).IsEqualTo(HttpStatusCode.Found); //302 Found

    var redirectUrl = response.Headers.Location;

    //assert expected redirect URL
    //...

    response = await _client.GetAsync(redirectUrl);       

    Check.That(response.IsSuccessStatusCode).IsTrue(); //200 OK
}
...