Как выполнить функциональный тест со страницей сервера Blazor, которая содержит клиентское соединение с концентратором signalR

Забыл о том, как выполнить функциональный тест для страницы сервера Blazor, содержащей соединение с клиентским концентратором signalR.

Пока я пробовал раскрутить WebApplicationFactory(WAF) из класса запуска SUT. Затем я копирую необходимые сервисы из WAF в сервисы тестового контекста BUnit.

Проблема возникает, когда страница сервера Blazor пытается подключиться к концентратору signalR, предоставленному WAF. System.Net.Http.HttpRequestException: исключение отказано в соединении (см. Списки ниже). Я думаю, это потому, что WAF не использует сокеты, т.е. предлагает сервер в памяти??

Как другие выполняют тесты для аналогичного сценария с помощью signalR и Blazor?

Тестировать пока

  [Fact]
        public async Task Test_RendersImage()
        {
            // initialise BUnit with services from WebApplicationFactory
            InitialiseBUnitServices();

            // publish an mqtt message to trigger sending event from signalR to Blazor server page
            // this is triggering back-end services as expected
            await _Server.MqttClient.PublishAsync(CreateMessageFromStream(_Stream));
            await Task.Delay(3000);

            // request bUnit to render the client page and listen for data from signal R here
           // fails to connect to signalR hub here
            var cut = RenderComponent<WebApp.Pages.Index>();

            // output markup to check that client page rendered the incoming data
            _Output.WriteLine($"{cut.Markup}");

            // await CompletedTask to allow compilation of this async test stub 
            await Task.CompletedTask;
        }


        /// <summary>Create an mqtt message from stream</summary>
        private ManagedMqttApplicationMessage CreateMessageFromStream(MemoryStream stream)
        {
            const string Topic = "shinobi/group/monitor/trigger";

            var message = new MqttApplicationMessageBuilder()
                .WithTopic(Topic)
                .WithPayload(stream.ToArray())
                .Build();

            return new ManagedMqttApplicationMessageBuilder()
                .WithApplicationMessage(message)
                .Build();
        }

        private void InitialiseBUnitServices()
        {
            // get services from WebApplicationFactory and inject into bUnit
            var hubProxyFactory = _Server.Factory.Services.GetRequiredService<IHubProxyFactory>();
            var loggerDetectionConverter = _Server.Factory.Services.GetRequiredService<ILogger<MotionDetectionConverter>>();
            var loggerIndexPage = _Server.Factory.Services.GetRequiredService<ILogger<WebApp.Pages.Index>>();
            var loggerInfoConverter = _Server.Factory.Services.GetRequiredService<ILogger<MotionInfoConverter>>();
            var loggerJsonVisitor = _Server.Factory.Services.GetRequiredService<ILogger<JsonVisitor>>();
            var loggerRepository = _Server.Factory.Services.GetRequiredService<ILogger<MotionDetectionRepository>>();
            var navManager = _Server.Factory.Services.GetRequiredService<NavigationManager>();
            var repository = _Server.Factory.Services.GetRequiredService<IMotionDetectionRepository>();

            Services.AddSingleton(typeof(IHubProxyFactory), hubProxyFactory);
            Services.AddScoped<ILogger<MotionDetectionConverter>>(sp => loggerDetectionConverter);
            Services.AddScoped<ILogger<WebApp.Pages.Index>>(sp => loggerIndexPage);
            Services.AddScoped<ILogger<MotionInfoConverter>>(sp => loggerInfoConverter);
            Services.AddScoped<ILogger<JsonVisitor>>(sp => loggerJsonVisitor);
            Services.AddScoped<ILogger<IMotionDetectionRepository>>(sp => loggerRepository);
            Services.AddScoped<MockNavigationManager>(sp => new MockNavigationManager());
            Services.AddScoped<IMotionDetectionRepository>(sp => repository);
        }

Страница сервера Blazor

  protected override async Task OnAfterRenderAsync(bool firstRender)
        {
            if (firstRender)
            {
                /// <summary>
                /// Looks like abstract base class NavigationManager also needs a mock or sub class for unit testing.
                /// Cannot resolve RemoteNavigationManager from container, it is an internal class. So for mocking purposes have injected a subclass for bUnit tests.
                /// </summary>
                var hubUrl = NavigationManager.BaseUri.TrimEnd('/') + "/motionhub";
                hubUrl = "http://localhost:5000/motionhub"; // hard code url for now 
                try
                {
                    /// <summary> Using wrapper to allow unit testing!</summary>
                    Logger.LogInformation("Index.razor page is performing initial render, connecting to secondary signalR hub");
                    Logger.LogInformation($"hubUrl is {hubUrl}");
                    hubConnection = HubConnectionBuilder.Create(
                        hubUrl,
                        JsonConvertersFactory.CreateDefaultJsonConverters
                        (
                            LoggerMotionDetection,
                            LoggerMotionInfo,
                            LoggerJsonVisitor
                        )
                    );

                    hubConnection.On<MotionDetection>("ReceiveMotionDetection", ReceiveMessage);
                    hubConnection.Closed += CloseHandler;

                    Logger.LogInformation("Starting HubConnection");
                    await hubConnection.StartAsync();
                    Logger.LogInformation("Index Razor Page initialised, listening on signalR hub => " + hubUrl.ToString());
                }
                catch (Exception e)
                {
                    Logger.LogError(e, "Encountered exception => " + e);
                }
            }
        }
  Encountered exception => System.Net.Http.HttpRequestException: Connection refused
       ---> System.Net.Sockets.SocketException (61): Connection refused
         at System.Net.Http.ConnectHelper.ConnectAsync(String host, Int32 port, CancellationToken cancellationToken)
         --- End of inner exception stack trace ---
         at System.Net.Http.ConnectHelper.ConnectAsync(String host, Int32 port, CancellationToken cancellationToken)
         at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean allowHttp2, CancellationToken cancellationToken)
         at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)
         at System.Net.Http.HttpConnectionPool.GetHttpConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)
         at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
         at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
         at Microsoft.AspNetCore.Http.Connections.Client.Internal.AccessTokenHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
         at Microsoft.AspNetCore.Http.Connections.Client.Internal.LoggingHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
         at System.Net.Http.HttpClient.FinishSendAsyncUnbuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
         at Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.NegotiateAsync(Uri url, HttpClient httpClient, ILogger logger, CancellationToken cancellationToken)
         at Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.GetNegotiationResponseAsync(Uri uri, CancellationToken cancellationToken)
         at Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.SelectAndStartTransport(TransferFormat transferFormat, CancellationToken cancellationToken)
         at Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.StartAsyncCore(TransferFormat transferFormat, CancellationToken cancellationToken)
         at System.Threading.Tasks.ForceAsyncAwaiter.GetResult()
         at Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.StartAsync(TransferFormat transferFormat, CancellationToken cancellationToken)
         at Microsoft.AspNetCore.Http.Connections.Client.HttpConnectionFactory.ConnectAsync(EndPoint endPoint, CancellationToken cancellationToken)
         at Microsoft.AspNetCore.Http.Connections.Client.HttpConnectionFactory.ConnectAsync(EndPoint endPoint, CancellationToken cancellationToken)
         at Microsoft.AspNetCore.SignalR.Client.HubConnection.StartAsyncCore(CancellationToken cancellationToken)
         at Microsoft.AspNetCore.SignalR.Client.HubConnection.StartAsyncInner(CancellationToken cancellationToken)
         at System.Threading.Tasks.ForceAsyncAwaiter.GetResult()
         at Microsoft.AspNetCore.SignalR.Client.HubConnection.StartAsync(CancellationToken cancellationToken)
         at WebApp.Pages.Index.OnAfterRenderAsync(Boolean firstRender) in /Users/simon/Development/Dotnet/CamFrontEnd/Src/WebApp/Pages/Index.razor.cs:line 167
      System.Net.Http.HttpRequestException: Connection refused
       ---> System.Net.Sockets.SocketException (61): Connection refused
         at System.Net.Http.ConnectHelper.ConnectAsync(String host, Int32 port, CancellationToken cancellationToken)
         --- End of inner exception stack trace ---
         at System.Net.Http.ConnectHelper.ConnectAsync(String host, Int32 port, CancellationToken cancellationToken)
         at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean allowHttp2, CancellationToken cancellationToken)
         at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)
         at System.Net.Http.HttpConnectionPool.GetHttpConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)
         at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
         at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
         at Microsoft.AspNetCore.Http.Connections.Client.Internal.AccessTokenHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
         at Microsoft.AspNetCore.Http.Connections.Client.Internal.LoggingHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
         at System.Net.Http.HttpClient.FinishSendAsyncUnbuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
         at Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.NegotiateAsync(Uri url, HttpClient httpClient, ILogger logger, CancellationToken cancellationToken)
         at Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.GetNegotiationResponseAsync(Uri uri, CancellationToken cancellationToken)
         at Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.SelectAndStartTransport(TransferFormat transferFormat, CancellationToken cancellationToken)
         at Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.StartAsyncCore(TransferFormat transferFormat, CancellationToken cancellationToken)
         at System.Threading.Tasks.ForceAsyncAwaiter.GetResult()
         at Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.StartAsync(TransferFormat transferFormat, CancellationToken cancellationToken)
         at Microsoft.AspNetCore.Http.Connections.Client.HttpConnectionFactory.ConnectAsync(EndPoint endPoint, CancellationToken cancellationToken)
         at Microsoft.AspNetCore.Http.Connections.Client.HttpConnectionFactory.ConnectAsync(EndPoint endPoint, CancellationToken cancellationToken)
         at Microsoft.AspNetCore.SignalR.Client.HubConnection.StartAsyncCore(CancellationToken cancellationToken)
         at Microsoft.AspNetCore.SignalR.Client.HubConnection.StartAsyncInner(CancellationToken cancellationToken)
         at System.Threading.Tasks.ForceAsyncAwaiter.GetResult()
         at Microsoft.AspNetCore.SignalR.Client.HubConnection.StartAsync(CancellationToken cancellationToken)

0 ответов

Другие вопросы по тегам