File: HubConnectionHandlerTestUtils\Utils.cs
Web Access
Project: src\src\SignalR\server\SignalR\test\Microsoft.AspNetCore.SignalR.Tests\Microsoft.AspNetCore.SignalR.Tests.csproj (Microsoft.AspNetCore.SignalR.Tests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR.Protocol;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Xunit;
 
namespace Microsoft.AspNetCore.SignalR.Tests;
 
public class HubConnectionHandlerTestUtils
{
    public static Type GetConnectionHandlerType(Type hubType)
    {
        var connectionHandlerType = typeof(HubConnectionHandler<>);
        return connectionHandlerType.MakeGenericType(hubType);
    }
 
    public static Type GetGenericType(Type genericType, Type hubType)
    {
        return genericType.MakeGenericType(hubType);
    }
 
    public static void AssertHubMessage(HubMessage expected, HubMessage actual)
    {
        // We aren't testing InvocationIds here
        switch (expected)
        {
            case CompletionMessage expectedCompletion:
                var actualCompletion = Assert.IsType<CompletionMessage>(actual);
                Assert.Equal(expectedCompletion.Error, actualCompletion.Error);
                Assert.Equal(expectedCompletion.HasResult, actualCompletion.HasResult);
                Assert.Equal(expectedCompletion.Result, actualCompletion.Result);
                break;
            case StreamItemMessage expectedStreamItem:
                var actualStreamItem = Assert.IsType<StreamItemMessage>(actual);
                Assert.Equal(expectedStreamItem.Item, actualStreamItem.Item);
                break;
            case InvocationMessage expectedInvocation:
                var actualInvocation = Assert.IsType<InvocationMessage>(actual);
 
                // Either both must have non-null invocationIds or both must have null invocation IDs. Checking the exact value is NOT desired here though as it could be randomly generated
                Assert.True((expectedInvocation.InvocationId == null && actualInvocation.InvocationId == null) ||
                    (expectedInvocation.InvocationId != null && actualInvocation.InvocationId != null));
                Assert.Equal(expectedInvocation.Target, actualInvocation.Target);
                Assert.Equal(expectedInvocation.Arguments, actualInvocation.Arguments);
                break;
            default:
                throw new InvalidOperationException($"Unsupported Hub Message type {expected.GetType()}");
        }
    }
 
    public static IServiceProvider CreateServiceProvider(Action<ServiceCollection> addServices = null, ILoggerFactory loggerFactory = null)
    {
        var services = new ServiceCollection();
        services.AddOptions()
            .AddLogging();
 
        services.AddSignalR()
            .AddMessagePackProtocol();
 
        addServices?.Invoke(services);
 
        if (loggerFactory != null)
        {
            services.AddSingleton(loggerFactory);
        }
 
        return services.BuildServiceProvider();
    }
 
    public static Connections.ConnectionHandler GetHubConnectionHandler(Type hubType, ILoggerFactory loggerFactory = null, Action<ServiceCollection> addServices = null)
    {
        var serviceProvider = CreateServiceProvider(addServices, loggerFactory);
        return (Connections.ConnectionHandler)serviceProvider.GetService(GetConnectionHandlerType(hubType));
    }
}
 
public class Result
{
    public string Message { get; set; }
#pragma warning disable IDE1006 // Naming Styles
    // testing casing
    public string paramName { get; set; }
#pragma warning restore IDE1006 // Naming Styles
}
 
public class TrackDispose
{
    public int DisposeCount = 0;
}
 
public class AsyncDisposable : IAsyncDisposable
{
    private readonly TrackDispose _trackDispose;
 
    public AsyncDisposable(TrackDispose trackDispose)
    {
        _trackDispose = trackDispose;
    }
 
    public ValueTask DisposeAsync()
    {
        _trackDispose.DisposeCount++;
        return default;
    }
}