#c# #asp.net #asp.net-mvc #asp.net-core #asp.net-web-api
#c# #asp.net #asp.net-mvc #asp.net-core #asp.net-web-api
Вопрос:
У меня действительно сложная ситуация. Мне нужно проверить, вызывается ли промежуточное программное обеспечение UseDeveloperExceptionPage при возникновении исключения. В попытке достичь этой цели я написал кучу вспомогательного кода.
DiagnosticExceptionAssembly.cs
namespace TestProjectSample
{
internal static class DiagnosticExceptionAssembly
{
internal const string Assembly = "Microsoft.AspNetCore.Diagnostics.UnhandledException";
}
}
ExceptionMessage.cs
namespace TestProjectSample
{
public struct ExceptionMessage
{
public string Message { get; set; }
}
}
ExceptionMessageObserver.cs
using System;
namespace TestProjectSample
{
public class ExceptionMessageObserver : IExceptionMessage
{
public string Message { get; set; }
public void OnCompleted()
{
throw new NotImplementedException();
}
public void OnError(Exception error)
{
throw new NotImplementedException();
}
public void OnNext(ExceptionMessage value)
{
Message = value.Message;
}
}
public interface IExceptionMessage : IObserver<ExceptionMessage>
{
string Message { get; set; }
}
}
ExceptionObserver.cs
using System;
using System.Collections.Generic;
using System.Reflection;
namespace TestProjectSample
{
public class ExceptionObserver : IObserver<KeyValuePair<string, object>>
{
private readonly IObserver<ExceptionMessage> _exceptionMessage;
public ExceptionObserver(IObserver<ExceptionMessage> exceptionMessage)
{
_exceptionMessage = exceptionMessage;
}
public void OnCompleted()
{
throw new NotImplementedException();
}
public void OnError(Exception error)
{
throw new NotImplementedException();
}
public void OnNext(KeyValuePair<string, object> value)
{
switch (value.Key)
{
case DiagnosticExceptionAssembly.Assembly:
var exceptionPayload = value.Value
.GetType()
.GetTypeInfo()
.GetDeclaredProperty("Exception")?
.GetValue(value.Value) as string;
_exceptionMessage.OnNext(new ExceptionMessage {Message = exceptionPayload});
break;
}
}
}
}
ExceptionSubscriber.cs
using System;
using System.Diagnostics;
namespace TestProjectSample
{
public class ExceptionSubscriber : IObserver<DiagnosticListener>
{
private readonly IObserver<ExceptionMessage> _exceptionMessage;
public ExceptionSubscriber(IObserver<ExceptionMessage> exceptionMessage)
{
_exceptionMessage = exceptionMessage;
}
public void OnCompleted()
{
throw new NotImplementedException();
}
public void OnError(Exception error)
{
throw new NotImplementedException();
}
public void OnNext(DiagnosticListener value)
{
if (string.Equals(DiagnosticExceptionAssembly.Assembly, value.Name))
{
value.Subscribe(new ExceptionObserver(_exceptionMessage));
}
}
}
}
DevExceptionPageFacts.cs
using System.Diagnostics;
using System.Net;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.Hosting;
using Xunit;
namespace TestProjectSample
{
public class DevExceptionPageFacts
{
private readonly IHostBuilder _hostBuilder;
private static readonly IExceptionMessage ExceptionMessage = new ExceptionMessageObserver();
public DevExceptionPageFacts()
{
FactSubscriber();
_hostBuilder = GenerateExceptionHostBuilder();
}
private static IHostBuilder GenerateExceptionHostBuilder()
{
return new HostBuilder()
.ConfigureWebHost(builder =>
{
builder.UseTestServer();
builder.Configure(applicationBuilder =>
{
applicationBuilder.UseDeveloperExceptionPage();
applicationBuilder.Run(context => throw new HttpResetTestException(1));
});
});
}
private static void FactSubscriber()
{
DiagnosticListener.AllListeners.Subscribe(new ExceptionSubscriber(ExceptionMessage));
}
[Fact]
public async Task Throw_DevelopmentPageException()
{
var host = await _hostBuilder.StartAsync();
using var client = host.GetTestClient();
var response = await client.GetAsync("/");
Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
Assert.NotNull(ExceptionMessage.Message);
}
}
}
Исследуя исходный код UseDeveloperExceptionPage, я заметил внедрение DiagnosticSource, поэтому я решил создать класс для прослушивания, когда генерируется исключение и перехватывается промежуточным программным обеспечением. Однако мой тест не проходит. Кто-нибудь может знать, как выполнить этот тест?
Комментарии:
1. Во-первых, почему??? Во-вторых, исходный код находится в Сети, поэтому тесты написаны сопровождающими ( github.com/dotnet/aspnetcore/blob /… )
2. @JeremyLakeman У меня есть библиотека, которая предоставляет промежуточное программное обеспечение, которое запускает промежуточное программное обеспечение страницы исключений только на случай, если какое-либо исключение выдается в любом контроллере, если оно было первым в конвейере промежуточного программного обеспечения. Это не ожидаемое поведение. Промежуточное программное обеспечение страницы исключений должно быть первым в конвейере промежуточного программного обеспечения, по крайней мере, в режиме разработки.
3. @JeremyLakeman В любом случае, я забыл, что я могу видеть не только исходный код, но и тест, написанный для любого фрагмента кода, связанного с . Сетевое ядро. Я обращу внимание на то, что тест был написан для этого случая, и я попытаюсь найти решение для моего случая. Спасибо!