Я создал GlobalExceptionHandler для минимального API и несколько модульных тестов для проверки обработчика.
Мой обработчик выглядит следующим образом:
< pre class="lang-cs Prettyprint-override">internal class GlobalExceptionHandler(ILoggerWrapper logger) : IExceptionHandler
{
///
public async ValueTask TryHandleAsync(HttpContext httpContext, Exception exception, CancellationToken cancellationToken)
{
ProblemDetails problemDetails = new()
{
Status = StatusCodes.Status500InternalServerError,
//TODO: Build a visible endpoint to describe the exception CV-27246
Type = "https://httpstatuses.com/500",
Detail = exception.StackTrace
};
Action logAction = logger.LogCritical;
switch (exception)
{
case OperationCanceledException:
problemDetails.Title = "The operation has been canceled.";
break;
case OutOfMemoryException:
problemDetails.Title = "There was an error, Out of memory. Please see logs for more information.";
break;
case StackOverflowException:
problemDetails.Title = "There was an error, StackOverflow. Please see logs for more information.";
break;
case SEHException:
problemDetails.Title = "There was an error, SEHException. Please see logs for more information.";
break;
default:
logAction = logger.LogError;
problemDetails.Status = StatusCodes.Status417ExpectationFailed;
//TODO: Build a visible endpoint to describe the exception CV-27246
problemDetails.Type = "https://httpstatuses.com/417";
problemDetails.Title = $"{exception.Message} Please see logs for more information.";
break;
}
logAction(exception);
httpContext.Response.StatusCode = problemDetails.Status.HasValue ?
problemDetails.Status.Value :
StatusCodes.Status500InternalServerError;
httpContext.Response.ContentType = "application/json";
await httpContext.Response.WriteAsJsonAsync(problemDetails, cancellationToken);
var canContinue = logAction != logger.LogCritical;
return canContinue;
}
}
Это работает и возвращает false при возникновении одной из вышеуказанных ошибок.
В моем интеграционном тесте я добавил:
protected override void ConfigureWebHost(IWebHostBuilder builder) {
builder.Configure(app =>
{
app.UseExportService();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("throw-out-of-memory", UnhandledExceptionEndpoints.ThrowOutOfMemory);
endpoints.MapGet("throw-stack-overflow", UnhandledExceptionEndpoints.ThrowStackOverflow);
endpoints.MapGet("throw-seh", UnhandledExceptionEndpoints.ThrowSEHException);
endpoints.MapGet("throw-handeled", UnhandledExceptionEndpoints.ThrowHandledException);
});
});
}
Который просто выдает исключение из того, что запрошено.
И модульные тесты выглядят так:
[Fact]
public async Task OperationCanceledException_ShouldReturn500()
{
//Arrange
var client = _factory.CreateClient();
HttpResponseMessage? response = null;
//Act
response = await client.GetAsync("throw-out-of-memory");
var problemDetails = await response.Content.ReadFromJsonAsync();
//Assert
response.IsSuccessStatusCode.Should().BeFalse();
problemDetails.Status.Should().Be(500);
problemDetails.Type.Should().Be("https://httpstatuses.com/500");//TODO: Build a visible endpoint to describe the exception CV-27246
problemDetails.Title.Should().Be("There was an error, Out of memory. please see logs for more information.");
}
До недавнего времени все это работало правильно. Кажется, что на CI/CD он работает нормально, но когда я запускаю его локально, я получаю следующую ошибку:
System.Net.Http.HttpRequestException Error while copying content to a stream.
at System.Net.Http.HttpContent.LoadIntoBufferAsyncCore(Task serializeToStreamTask, MemoryStream tempBuffer)
at System.Net.Http.HttpClient.g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)
at ExportService.Tests.Intergration.Middleware.GlobalExceptionHandlerTests.OperationCanceledException_ShouldReturn500() in C:\Users\james.tays\source\repos\Components\src\ExportService\ExportService.Tests.Intergration\Middleware\GlobalExceptionHandlerTests.cs:line 72
at Xunit.Sdk.TestInvoker`1.c__DisplayClass47_0.d.MoveNext() in /_/src/xunit.execution/Sdk/Frameworks/Runners/TestInvoker.cs:line 259
--- End of stack trace from previous location ---
at Xunit.Sdk.ExecutionTimer.AggregateAsync(Func`1 asyncAction) in /_/src/xunit.execution/Sdk/Frameworks/ExecutionTimer.cs:line 48
at Xunit.Sdk.ExceptionAggregator.RunAsync(Func`1 code) in /_/src/xunit.core/Sdk/ExceptionAggregator.cs:line 90
System.IO.IOException
at Microsoft.AspNetCore.TestHost.ResponseBodyReaderStream.CheckAborted()
at Microsoft.AspNetCore.TestHost.ResponseBodyReaderStream.ReadAsync(Memory`1 buffer, CancellationToken cancellationToken)
at System.IO.Stream.g__Core|27_0(Stream source, Stream destination, Int32 bufferSize, CancellationToken cancellationToken)
at System.Net.Http.HttpContent.LoadIntoBufferAsyncCore(Task serializeToStreamTask, MemoryStream tempBuffer)
System.OutOfMemoryException OutOfMemory
at ExportService.Tests.Intergration.Endpoints.UnhandledExceptionEndpoints.ThrowOutOfMemory() in C:\Users\james.tays\source\repos\Components\src\ExportService\ExportService.Tests.Intergration\Endpoints\UnhandledExceptionEndpoints.cs:line 15
at lambda_method19(Closure, Object, HttpContext)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.Invoke(HttpContext httpContext)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddlewareImpl.Invoke(HttpContext context)
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddlewareImpl.HandleException(HttpContext context, ExceptionDispatchInfo edi)
at Microsoft.AspNetCore.TestHost.HttpContextBuilder.c__DisplayClass23_0.d.MoveNext()
Во время отладки, которую мне никогда не удастся:
var problemDetails = await response.Content.ReadFromJsonAsync
();
Можете ли вы объяснить, почему это исключение не обрабатывается? Я только что вернул true в обработчике, и он по-прежнему ведет себя так же.
И в моих сервисах у меня есть следующее:
services.AddProblemDetails();
services.AddExceptionHandler();
Подробнее здесь: https://stackoverflow.com/questions/791 ... o-a-stream
GlobalExceptionHander Ошибка теста Ошибка при копировании содержимого в поток ⇐ C#
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение
-
-
GlobalExceptionHander Ошибка теста Ошибка при копировании содержимого в поток
Anonymous » » в форуме C# - 0 Ответы
- 11 Просмотры
-
Последнее сообщение Anonymous
-
-
-
GlobalExceptionHander Ошибка теста Ошибка при копировании содержимого в поток
Anonymous » » в форуме C# - 0 Ответы
- 16 Просмотры
-
Последнее сообщение Anonymous
-
-
-
System.Net.Http.HttpRequestException Ошибка при копировании содержимого в поток
Anonymous » » в форуме C# - 0 Ответы
- 22 Просмотры
-
Последнее сообщение Anonymous
-