File: HubServerProxyGeneratorTests.cs
Web Access
Project: src\src\SignalR\clients\csharp\Client\test\UnitTests\Microsoft.AspNetCore.SignalR.Client.Tests.csproj (Microsoft.AspNetCore.SignalR.Client.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.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Channels;
using System.Threading.Tasks;
using Moq;
using Xunit;
 
namespace Microsoft.AspNetCore.SignalR.Client.Tests;
 
[AttributeUsage(AttributeTargets.Method)]
internal class HubServerProxyAttribute : Attribute
{
 
}
 
internal static partial class HubServerProxyExtensions
{
    [HubServerProxy]
    public static partial T GetHubServer<T>(this HubConnection conn);
}
 
public class HubServerProxyGeneratorTests
{
    public interface IMyHub
    {
        Task GetNothing();
        Task<int> GetScalar();
        Task<List<int>> GetCollection();
        Task<int> SetScalar(int a);
        Task<List<int>> SetCollection(List<int> a);
        Task<ChannelReader<int>> StreamToClientViaChannel();
        Task<ChannelReader<int>> StreamToClientViaChannelWithToken(CancellationToken cancellationToken);
        IAsyncEnumerable<int> StreamToClientViaEnumerableWithToken(CancellationToken cancellationToken);
        Task StreamFromClientViaChannel(ChannelReader<int> reader);
        Task StreamFromClientViaEnumerable(IAsyncEnumerable<int> reader);
        Task<int> StreamFromClientButAlsoReturnValue(ChannelReader<int> reader);
        Task<ChannelReader<int>> StreamBidirectionalViaChannel(ChannelReader<float> reader);
        Task<ChannelReader<int>> StreamBidirectionalViaChannelWithToken(ChannelReader<float> reader, CancellationToken cancellationToken);
        IAsyncEnumerable<int> StreamBidirectionalViaEnumerable(IAsyncEnumerable<float> reader);
        IAsyncEnumerable<int> StreamBidirectionalViaEnumerableWithToken(IAsyncEnumerable<float> reader, CancellationToken cancellationToken);
        ValueTask ReturnValueTask();
        ValueTask<int> ReturnGenericValueTask();
        Task<int?> HandleNullables(float? nullable);
    }
 
    [Fact]
    public async Task GetNothing()
    {
        // Arrange
        var mockConn = MockHubConnection.Get();
        mockConn
            .Setup(x => x.InvokeCoreAsync(
                nameof(IMyHub.GetNothing),
                typeof(object),
                Array.Empty<object>(),
                default))
            .Returns(Task.FromResult(default(object)));
        var conn = mockConn.Object;
        var myHub = conn.GetHubServer<IMyHub>();
 
        // Act
        await myHub.GetNothing();
 
        // Assert
        mockConn.VerifyAll();
    }
 
    [Fact]
    public async Task GetScalar()
    {
        // Arrange
        var mockConn = MockHubConnection.Get();
        mockConn
            .Setup(x => x.InvokeCoreAsync(
                nameof(IMyHub.GetScalar),
                typeof(int),
                Array.Empty<object>(),
                default))
            .Returns(Task.FromResult((object)10));
        var conn = mockConn.Object;
        var myHub = conn.GetHubServer<IMyHub>();
 
        // Act
        var result = await myHub.GetScalar();
 
        // Assert
        mockConn.VerifyAll();
        Assert.Equal(10, result);
    }
 
    [Fact]
    public async Task GetCollection()
    {
        // Arrange
        var mockConn = MockHubConnection.Get();
        mockConn
            .Setup(x => x.InvokeCoreAsync(
                nameof(IMyHub.GetCollection),
                typeof(List<int>),
                Array.Empty<object>(),
                default))
            .Returns(Task.FromResult((object)new List<int> { 10 }));
        var conn = mockConn.Object;
        var myHub = conn.GetHubServer<IMyHub>();
 
        // Act
        var result = await myHub.GetCollection();
 
        // hello
 
        // Assert
        mockConn.VerifyAll();
        Assert.NotNull(result);
        Assert.Collection(result, item => Assert.Equal(10, item));
    }
 
    [Fact]
    public async Task SetScalar()
    {
        // Arrange
        var mockConn = MockHubConnection.Get();
        mockConn
            .Setup(x => x.InvokeCoreAsync(
                nameof(IMyHub.SetScalar),
                typeof(int),
                It.Is<object[]>(y => ((object[])y).Any(z => (int)z == 20)),
                default))
            .Returns(Task.FromResult((object)10));
        var conn = mockConn.Object;
        var myHub = conn.GetHubServer<IMyHub>();
 
        // Act
        var result = await myHub.SetScalar(20);
 
        // Assert
        mockConn.VerifyAll();
        Assert.Equal(10, result);
    }
 
    [Fact]
    public async Task SetCollection()
    {
        // Arrange
        var arg = new List<int>() { 20 };
        var mockConn = MockHubConnection.Get();
        mockConn
            .Setup(x => x.InvokeCoreAsync(
                nameof(IMyHub.SetCollection),
                typeof(List<int>),
                It.Is<object[]>(y => ((object[])y).Any(z => (List<int>)z == arg)),
                default))
            .Returns(Task.FromResult((object)new List<int> { 10 }));
        var conn = mockConn.Object;
        var myHub = conn.GetHubServer<IMyHub>();
 
        // Act
        var result = await myHub.SetCollection(arg);
 
        // Assert
        mockConn.VerifyAll();
        Assert.NotNull(result);
        Assert.Collection(result, item => Assert.Equal(10, item));
    }
 
    [Fact]
    public async Task StreamToClient()
    {
        // Arrange
        var channel = Channel.CreateUnbounded<object>();
        var channelForEnumerable = Channel.CreateUnbounded<int>();
        var asyncEnumerable = channelForEnumerable.Reader.ReadAllAsync();
        var cts = new CancellationTokenSource();
        var token = cts.Token;
        var mockConn = MockHubConnection.Get();
        mockConn
            .Setup(x => x.StreamAsChannelCoreAsync(
                nameof(IMyHub.StreamToClientViaChannel),
                typeof(int),
                Array.Empty<object>(),
                default))
            .Returns(Task.FromResult(channel.Reader));
        mockConn
            .Setup(x => x.StreamAsChannelCoreAsync(
                nameof(IMyHub.StreamToClientViaChannelWithToken),
                typeof(int),
                Array.Empty<object>(),
                token))
            .Returns(Task.FromResult(channel.Reader));
        mockConn
            .Setup(x => x.StreamAsyncCore<int>(
                nameof(IMyHub.StreamToClientViaEnumerableWithToken),
                Array.Empty<object>(),
                token))
            .Returns(asyncEnumerable);
        var conn = mockConn.Object;
        var myHub = conn.GetHubServer<IMyHub>();
 
        // Act
        _ = await myHub.StreamToClientViaChannel();
        _ = await myHub.StreamToClientViaChannelWithToken(token);
        _ = myHub.StreamToClientViaEnumerableWithToken(token);
 
        // Assert
        mockConn.VerifyAll();
    }
 
    [Fact]
    public async Task StreamFromClient()
    {
        // Arrange
        var channel = Channel.CreateUnbounded<int>();
        var channelReader = channel.Reader;
        var channelForEnumerable = Channel.CreateUnbounded<int>();
        var asyncEnumerable = channelForEnumerable.Reader.ReadAllAsync();
        var mockConn = MockHubConnection.Get();
        mockConn
            .Setup(x => x.SendCoreAsync(
                nameof(IMyHub.StreamFromClientViaChannel),
                It.Is<object[]>(y => ((object[])y).Any(z => (ChannelReader<int>)z == channelReader)),
                default))
            .Returns(Task.CompletedTask);
        mockConn
            .Setup(x => x.SendCoreAsync(
                nameof(IMyHub.StreamFromClientViaEnumerable),
                It.Is<object[]>(y => ((object[])y).Any(z => (IAsyncEnumerable<int>)z == asyncEnumerable)),
                default))
            .Returns(Task.CompletedTask);
        mockConn
            .Setup(x => x.InvokeCoreAsync(
                nameof(IMyHub.StreamFromClientButAlsoReturnValue),
                typeof(int),
                It.Is<object[]>(y => ((object[])y).Any(z => (ChannelReader<int>)z == channelReader)),
                default))
            .Returns(Task.FromResult((object)6));
        var conn = mockConn.Object;
        var myHub = conn.GetHubServer<IMyHub>();
 
        // Act
        await myHub.StreamFromClientViaChannel(channelReader);
        await myHub.StreamFromClientViaEnumerable(asyncEnumerable);
        var result = await myHub.StreamFromClientButAlsoReturnValue(channelReader);
 
        // Assert
        mockConn.VerifyAll();
        Assert.Equal(6, result);
    }
 
    [Fact]
    public async Task BidirectionalStream()
    {
        // Arrange
        var argChannel = Channel.CreateUnbounded<float>();
        var retChannel = Channel.CreateUnbounded<object>();
        var retChannelReader = retChannel.Reader;
        var argChannelForEnumerable = Channel.CreateUnbounded<float>();
        var argEnumerable = argChannelForEnumerable.Reader.ReadAllAsync();
        var retChannelForEnumerable = Channel.CreateUnbounded<int>();
        var retEnumerable = retChannelForEnumerable.Reader.ReadAllAsync();
        var cts = new CancellationTokenSource();
        var token = cts.Token;
        var mockConn = MockHubConnection.Get();
        mockConn
            .Setup(x => x.StreamAsChannelCoreAsync(
                nameof(IMyHub.StreamBidirectionalViaChannel),
                typeof(int),
                It.Is<object[]>(y => ((object[])y).Any(z => z is ChannelReader<float>)),
                default))
            .Returns(Task.FromResult(retChannelReader));
        mockConn
            .Setup(x => x.StreamAsChannelCoreAsync(
                nameof(IMyHub.StreamBidirectionalViaChannelWithToken),
                typeof(int),
                It.Is<object[]>(y => ((object[])y).Any(z => z is ChannelReader<float>)),
                token))
            .Returns(Task.FromResult(retChannelReader));
        mockConn
            .Setup(x => x.StreamAsyncCore<int>(
                nameof(IMyHub.StreamBidirectionalViaEnumerable),
                It.Is<object[]>(y => ((object[])y).Any(z => z is IAsyncEnumerable<float>)),
                default))
            .Returns(retEnumerable);
        mockConn
            .Setup(x => x.StreamAsyncCore<int>(
                nameof(IMyHub.StreamBidirectionalViaEnumerableWithToken),
                It.Is<object[]>(y => ((object[])y).Any(z => z is IAsyncEnumerable<float>)),
                token))
            .Returns(retEnumerable);
        var conn = mockConn.Object;
        var myHub = conn.GetHubServer<IMyHub>();
 
        // Act
        _ = await myHub.StreamBidirectionalViaChannel(argChannel.Reader);
        _ = await myHub.StreamBidirectionalViaChannelWithToken(argChannel.Reader, token);
        _ = myHub.StreamBidirectionalViaEnumerable(argEnumerable);
        _ = myHub.StreamBidirectionalViaEnumerableWithToken(argEnumerable, token);
 
        // Assert
        mockConn.VerifyAll();
    }
 
    [Fact]
    public async Task ReturnValueTask()
    {
        // Arrange
        var mockConn = MockHubConnection.Get();
        mockConn
            .Setup(x => x.InvokeCoreAsync(
                nameof(IMyHub.ReturnValueTask),
                typeof(object),
                Array.Empty<object>(),
                default))
            .Returns(Task.FromResult(default(object)));
        mockConn
            .Setup(x => x.InvokeCoreAsync(
                nameof(IMyHub.ReturnGenericValueTask),
                typeof(int),
                Array.Empty<object>(),
                default))
            .Returns(Task.FromResult((object)10));
        var conn = mockConn.Object;
        var myHub = conn.GetHubServer<IMyHub>();
 
        // Act
        await myHub.ReturnValueTask();
        var result = await myHub.ReturnGenericValueTask();
 
        // Assert
        mockConn.VerifyAll();
        Assert.Equal(10, result);
    }
}