Should.ThrowAsync 未捕获来自 HttpClient.GetAsync() 请求的异常

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

在我们的项目中,我们有一个由前同事编写的测试,该测试正在向端点发出请求,该端点应该并且确实在抛出异常后返回 500 - InternalServerError (使用 Shouldly 检查这一点)。

为了演示目的,简化了以下代码。

端点:

[HttpGet]
[Route("machines/{idMachine:guid}/admin")]
[Authorize(Policy = Policies.RequireMachineCustomerCheck)]
public IActionResult MachineEditor(Guid idMachine)
{
    // Lookup machine...

    if (machine == null)
    {
        throw new Exception("Exception");
    }
}

测试:

[Fact]
public async Task MachineNotFoundShouldThrowException()
{
    var idMachine = Guid.NewGuid();
    var uri = new Uri($"/machines/{idMachine}/admin", UriKind.Relative);
    var httpClient = new HttpClient();

    var response = await httpClient.GetAsync(uri);
    response.StatusCode.ShouldBe(HttpStatusCode.InternalServerError);
}

但是,自从从 .NET Core 3.1 更新到 .NET 6 后,我们的 Azure DevOps YAML 部署管道在运行测试时报告异常。然而,它是从不同的代码路径抛出的,在我们端点的授权策略中:

执行请求时发生未处理的异常。 System.Exception:在服务器的内存缓存中找不到机器 ID 为 7f6825f9-3e4c-4d32-aace-ec9128394e0c。要么缓存已过时 或者ID不正确。 在Proseal.Portal.Services.Utilities.CacheHelper.GetProVisionMachine(Guid idMachine)中 D:\ s \ Proseal \ Portal.Services \ Utilities \ CacheHelper.cs:第72行 在Proseal.Portal.Server.Common.Authorization.MachineCustomerCheckHandler.HandleRequirementAsync(AuthorizationHandlerContext 上下文,MachineCustomerCheck 要求)中 D:\ s \ Proseal \ Portal.Server \ Common \ Authorization \ MachineCustomerCheck.cs:行 83 在 Microsoft.AspNetCore.Authorization.AuthorizationHandler

1.HandleAsync(AuthorizationHandlerContext context) at Microsoft.AspNetCore.Authorization.DefaultAuthorizationService.AuthorizeAsync(ClaimsPrincipal user, Object resource, IEnumerable
1 要求) 在 Microsoft.AspNetCore.Authorization.Policy.PolicyEvaluator.AuthorizeAsync(AuthorizationPolicy 策略、AuthenticateResult 身份验证结果、HttpContext 上下文、 对象资源) 在 Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext 语境) 在Proseal.Portal.Server.Common.Middleware.AuthenticationForStaticFilesMiddleware.InvokeAsync(HttpContext 上下文,RequestDelegate 接下来)中 D:\s\Proseal\Portal.Server\Common\Middleware\AuthenticationForStaticFilesMiddleware.cs:行 43 在 Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.<>c__DisplayClass6_1.d.MoveNext()

授权策略注册:

public class Startup
{
   public void ConfigureServices(IServiceCollection services)
   {
      services.AddAuthorization(options =>
      {
         options.AddPolicy(Policies.RequireMachineCustomerCheck, policy => policy.Requirements.Add(new MachineCustomerCheck()));
      }
   }
}

验证处理程序:

public class MachineCustomerCheckHandler : AuthorizationHandler<MachineCustomerCheck>
{
    protected override Task HandleRequirementAsync()
    {
        // Lookup machine

        if (machine == null)
        {
            throw new Exception("Exception");
        }
    }

在 Visual Studio 2022 的测试资源管理器中本地运行测试不会引发异常或失败,但对其进行调试可确认引发异常。由于返回了 500,测试仍然通过。不知道为什么部署管道的行为与 VS 不同。

将测试包装在 try-catch 中是我的第一个想法,但异常没有被捕获。

try
{
    var response = await httpClient.GetAsync(uri);
    response.StatusCode.ShouldBe(HttpStatusCode.InternalServerError);
}
catch (Exception exception)
{
    exception.Message.ShouldBe("Exception");
}

经过一番谷歌搜索后,我改变了这一点,但得到了相同的行为。

try
{
    await Task.Run(async () => await httpClient.GetAsync(uri));
}
catch (Exception exception)
{
    exception.Message.ShouldBe("Exception");
}

我也尝试过使用 Shouldly 的 ShouldThrowAsync 方法:https://docs.shouldly.org/documentation/exceptions/throw#shouldthrowasync,但这也无法捕获异常。

Func<Task> func = async () => await httpClient.GetAsync(uri);

await Should.ThrowAsync<Exception>(func);

担心异步代码(因此异常)包含在单独的线程中可能存在另一个问题,但我的异步知识不是最好的,所以我缺乏其他可以尝试的东西。

c# .net asynchronous shouldly
1个回答
0
投票

例如,如果您使用 XUnit,您可能会遇到如下异常:

 await Assert.ThrowsAsync<ExceptionType>(() => testContext.httpClient.GetAsync(uri));

如果您继续遇到不属于此类别的异常,请检查您的 DI。过去曾遇到过未正确捕获/抛出 DI 错误的情况。

© www.soinside.com 2019 - 2024. All rights reserved.