Как проверить, было ли вызвано промежуточное программное обеспечение UseDeveloperExceptionPage в ASP.NET Ядро?

#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 В любом случае, я забыл, что я могу видеть не только исходный код, но и тест, написанный для любого фрагмента кода, связанного с . Сетевое ядро. Я обращу внимание на то, что тест был написан для этого случая, и я попытаюсь найти решение для моего случая. Спасибо!