【问题标题】:How to mock SignalR used in a service layer如何模拟服务层中使用的 SignalR
【发布时间】:2020-09-03 20:49:40
【问题描述】:

我需要测试ClientConnectionProvider 类,但不能在下面给出的测试类中模拟private IHubContext<SignalrServerHub, IBroadcast> HubContext { get; set; }。如何在测试类中使用hubcontext 模拟客户端?

public class ClientConnectionProvider : IConnectionProvider
{
    private readonly ILogger<ClientConnectionProvider> logger;
    
    private IHubContext<SignalrServerHub, IBroadcast> HubContext { get; set;}
    
    /// <summary>
    /// Initializes a new instance of the <see cref="ClientConnectionProvider"/> class.
    /// </summary>
    /// <param name="logger"></param>
    /// <param name="hubContext"></param>
    public ClientConnectionProvider(ILogger<ClientConnectionProvider> logger, IHubContext<SignalrServerHub, IBroadcast> hubContext)
    {
        this.logger = logger;
        HubContext = hubContext;
    }
    
    /// <summary>
    /// To create and save  a connection based on clients on connect.
    /// </summary>
    /// <param name="groupName"><see cref="string"/>.</param>
    /// <returns>Task of <see cref="Task"/>.</returns>
    public async Task<ServiceMethodResponse> SubscribeConnectionToAGroup(ClientConnection connection)
    {
        await HubContext.Groups.AddToGroupAsync(connection.ConnectionId, "HubUsers");
    
        return new ServiceMethodResponse() 
        {
            IsSuccess = true,
            IsValid = true,
            Message = "Subscribed to a group"
        };
    }
}

public class ConnectionProviderTest
{
    private Mock<ILogger<ClientConnectionProvider>> logger;
    private Mock<IDispatcher> dispatcher;
    private Mock<IServiceProvider> serviceProvider;
    private Mock<IConnectionProvider> connectionProvider;
    private Mock<IHubContext<SignalrServerHub, IBroadcast>> HubContext;
    //Mock<IClientProxy> mockClientProxy = new Mock<IClientProxy>();
    private Mock<IClientProxy> mockClientProxy = new Mock<IClientProxy>();    

    /// <summary>
    /// Initializes a new instance of the <see cref="ConnectionProviderTest"/> class.
    /// </summary>
    public ConnectionProviderTest()
    {
        this.logger = new Mock<ILogger<ClientConnectionProvider>>();
        this.HubContext = new Mock<IHubContext<SignalrServerHub, IBroadcast>>();
        this.connectionProvider = new Mock<IConnectionProvider>();
        this.dispatcher = new Mock<IDispatcher>();
    }

    [Fact]
    public async Task SendNotificationToAllFoundSuccess()
    {    
        Mock<IHubClients> mockClients = new Mock<IHubClients>();
        Mock<IClientProxy> mockClientProxy = new Mock<IClientProxy>();
        mockClients.Setup(clients => clients.All).Returns(mockClientProxy.Object);
        ClientConnectionProvider clientConnectionProvider = new ClientConnectionProvider( this.logger.Object, this.HubContext.Object);

        this.HubContext.Setup(x => x.Clients).Returns(() => (IHubClients<IBroadcast>)mockClients.Object);

        NotificationPayload payload = new NotificationPayload
        {
            Message = "RnadomHashString",
            SubscriptionTypes = new List<SubscriptionType>() { new SubscriptionType { SubscriptionTypeName = "HubUsers" } },
        };

        ServiceMethodResponse response = await clientConnectionProvider.SendNotificationToAll(payload).ConfigureAwait(true);
        Assert.True(response.IsValid);
    }
}

如何测试 ClientConnectionProvider 的方法?出现错误 System.InvalidCastException : 无法将 'Castle.Proxies.IHubClients`1Proxy' 类型的对象转换为 'Microsoft.AspNetCore.SignalR.IHubClients`1[Platform.PushNotification.Services.SignalRHub.IBroadcast]' 类型。

【问题讨论】:

    标签: .net .net-core mocking signalr xunit


    【解决方案1】:

    也许我之前没有说清楚。我的意思是:

    • 您可以将 IHubContext 中使用的 SignalrServerHub 实例包装在您的实际代码中。
    • 然后您可以模拟该界面。

    您遇到的异常是因为类 SignalrServerHub 无法模拟,因为它没有接口。

    // The wrapper interface
    public interface ISignalrServerHub
    {
        // Specify the methods / properties of SignalrServerHub, which you need
        void SomeMethodYouNeed();
        bool SomeMethodWithReturnValue();
    }
    
    // The wrapper
    public class WrappedSignalrServerHub : ISignalrServerHub
    {
        private SingalrServerHub _wrappedInstance;
        
        public WrappedSignalrServerHub(SignalrServerHub instance)
        {
            _wrappedInstance = instance; // TODO add null check
        }
        
        public void SomeMethodYouNeed()
        {
            _wrappedInstance.SomeMethodYouNeed();
        }
        
        public bool SomeMethodWithReturnValue()
        {
            return _wrappedInstance.SomeMethodWithReturnValue();
        }
    }
    
    // The changed class
    public class ClientConnectionProvider : IConnectionProvider
    {
        private readonly ILogger<ClientConnectionProvider> logger;
        
        private IHubContext<ISignalrServerHub, IBroadcast> HubContext { get; set;}
        
        /// <summary>
        /// Initializes a new instance of the <see cref="ClientConnectionProvider"/> class.
        /// </summary>
        /// <param name="logger"></param>
        /// <param name="hubContext"></param>
        public ClientConnectionProvider(ILogger<ClientConnectionProvider> logger, IHubContext<ISignalrServerHub, IBroadcast> hubContext)
        {
            this.logger = logger;
            HubContext = hubContext;
        }
        
        // [snipped for brevity]
    }
    
    // The changed test
    public class ConnectionProviderTest
    {
        // [snipped for brevity]
        private Mock<IHubContext<ISignalrServerHub, IBroadcast>> HubContext;
        // [snipped for brevity]
    
        /// <summary>
        /// Initializes a new instance of the <see cref="ConnectionProviderTest"/> class.
        /// </summary>
        public ConnectionProviderTest()
        {
            this.logger = new Mock<ILogger<ClientConnectionProvider>>();
            this.HubContext = new Mock<IHubContext<ISignalrServerHub, IBroadcast>>();
            this.connectionProvider = new Mock<IConnectionProvider>();
            this.dispatcher = new Mock<IDispatcher>();
        }
    
        
        // [snipped for brevity]
    }
    

    【讨论】:

    • 这没有帮助。
    • 我更新了我的答案。也许这会满足您的需求。
    猜你喜欢
    • 1970-01-01
    • 2012-12-08
    • 2021-12-10
    • 2019-07-20
    • 1970-01-01
    • 2016-01-25
    • 2020-06-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多