Как имитировать SignalR, используемый на уровне сервиса

#.net #.net-core #mocking #signalr #xunit

#.net #.net-ядро #издевательство #signalr #xunit ( единица измерения ) #xunit

Вопрос:

Мне нужно протестировать 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? Получение ошибки системы.Исключение InvalidCastException : невозможно привести объект типа 'Castle.Proxies.IHubClients`1Proxy' к типу 'Microsoft.AspNetCore.SignalR.IHubClients`1[Platform.PushNotification.Services.SignalRHub.IBroadcast]' .

Ответ №1:

Возможно, я не совсем ясно выразился раньше. Что я хотел сказать:

  • вы могли бы обернуть экземпляр SignalrServerHub, используемый в IHubContext, в свой реальный код.
  • затем вы могли бы издеваться над этим интерфейсом.

Исключение, которое вы получаете, связано с тем, что класс 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]
}
  

Комментарии:

1. Это не помогает.

2. Я обновил свой ответ. Возможно, это удовлетворит ваши потребности.