如何在C# 3.1 net core中测试用户请求取消(HttpClient CancellationToken似乎从3.1开始就一直在抛出)。

问题描述 投票:0回答:1

最近我想从dot.net升级到HttpClient netcoreapp2.2netcoreapp3.1. 我正在使用 https:/docs.microsoft.comen-usaspnetcoretestintegration-tests?view=aspnetcore-3.1。 来执行我的API实现的测试。

有一个测试是验证取消用户是返回499状态码(https:/httpstatuses.com499。). 这个功能的实现是通过中间件完成的。

在测试中,关键断言是这样的。

var tokenSource = new CancellationTokenSource();
var token = tokenSource.Token;
var client = this.CreateHttpClient(repositoryMock);
HttpResponseMessage responseMessage = null;
await Task.WhenAll(
    Task.Run(async () =>
        {
            await Task.Delay(500);
            tokenSource.Cancel();
        }),
    Task.Run(async () =>
        {
            responseMessage = await client.GetAsync(new Uri($"http://localhost/api/values/haxi?haxiIds={haxiGuid}"), token);
        }));
Assert.That(
    responseMessage.StatusCode,
    Is.EqualTo((HttpStatusCode)499));

在2. 2版本中,一切都很正常 服务器取消,返回499,HttpClient接收。

在3.1中,看起来服务器取消,返回499,但HttpClient总是抛出一个异常。

  Message: 
    System.OperationCanceledException : The operation was canceled.
  Stack Trace: 
    HttpClient.HandleFinishSendAsyncError(Exception e, CancellationTokenSource cts)
    HttpClient.FinishSendAsyncBuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
    <<Cancellation_ShouldReturn499>b__3>d.MoveNext() line 57
    --- End of stack trace from previous location where exception was thrown ---
    ControllerTests.Cancellation_ShouldReturn499() line 49
    GenericAdapter`1.BlockUntilCompleted()
    NoMessagePumpStrategy.WaitForCompletion(AwaitAdapter awaitable)
    AsyncToSyncAdapter.Await(Func`1 invoke)
    TestMethodCommand.RunTestMethod(TestExecutionContext context)
    TestMethodCommand.Execute(TestExecutionContext context)
    SimpleWorkItem.PerformWork()

我已经设置了一个完整的新解决方案来重现这个问题。https:/github.comschrufygroovyassert-api-cancellation。.

在3.1中是否有其他方法来验证用户取消的http请求的响应?还是我在3.1中对API的设置是错误的?是否中间件被执行了,但又被其他3.1的新特性所取代?

c# dotnet-httpclient asp.net-core-3.1 request-cancelling
1个回答
0
投票

看起来像行为的 HttpClient 从2.2改成了3.1

我能够通过使用自定义的 HttpMessageInvoker 而不是 HttpClient.

制作一些函数来创建一个 HttpMessageInvoker 正在使用 HttpMessageHandlerTestServer (使用WithWebHostBuilder的WebApplicationFactory。):

private HttpMessageInvoker CreateHttpMessageInvoker(Mock<IHaxiRepository> repositoryMock)
{
    return new HttpMessageInvoker(this.factory.WithWebHostBuilder(
        builder =>
        {
            builder.ConfigureTestServices(services =>
            {
                services.AddScoped(typeof(IHaxiRepository), provider => repositoryMock.Object);
            });
        }).Server.CreateHandler(), true);
}

用那个代替 HttpClient:

var tokenSource = new CancellationTokenSource();
var token = tokenSource.Token;
using var httpMessageInvoker = this.CreateHttpMessageInvoker(repositoryMock);
HttpResponseMessage responseMessage = null;
await Task.WhenAll(
    Task.Run(async () =>
        {
            await Task.Delay(500);
            tokenSource.Cancel();
        }),
    Task.Run(async () =>
        {
            responseMessage = await httpMessageInvoker.SendAsync(
                new HttpRequestMessage(HttpMethod.Get, new Uri($"http://localhost/api/values/haxi?haxiIds={haxiGuid}")),
                token);
        }));
Assert.That(
    responseMessage.StatusCode,
    Is.EqualTo((HttpStatusCode)499));
© www.soinside.com 2019 - 2024. All rights reserved.