Course contentsShow
← C#
Lesson 1694 of 1,90815. Software Quality and TestingFree lesson

Testing SignalR Hubs

Simulate real-time message broadcasting to test client-server communication.

In this lesson, you will learn how to verify real-time message broadcasting by mocking the SignalR IHubCallerClients and IClientProxy interfaces to ensure your hub correctly dispatches data.

The Challenge of Real-Time Testing

When testing SignalR hubs, the complexity lies in the "fire-and-forget" nature of real-time communication. You aren't just asserting a return value; you are verifying that the hub effectively "broadcasts" a message to a specific group, user, or all connected clients. Because SignalR relies on complex internal proxies, we use Moq to intercept calls to the Clients property.

Simulating the Broadcast

To test a hub, you must mock the IHubCallerClients interface. This allows you to verify that when a client triggers a hub method, the server subsequently invokes a client-side method (e.g., ReceiveMessage) with the expected payload.

Consider a simple ChatHub that sends a message to all clients:

[Fact]
public async Task SendMessage_ShouldBroadcastToAllClients()
{
    // Arrange
    var mockClients = new Mock<IHubCallerClients>();
    var mockClientProxy = new Mock<IClientProxy>();
    
    mockClients.Setup(clients => clients.All).Returns(mockClientProxy.Object);
    
    var hub = new ChatHub { Clients = mockClients.Object };

    // Act
    await hub.SendMessage("Hello World");

    // Assert
    mockClientProxy.Verify(
        client => client.SendCoreAsync("ReceiveMessage", 
            It.Is<object[]>(o => o.Contains("Hello World")), default),
        Times.Once);
}

Why This Matters

By mocking IClientProxy, you avoid spinning up a full integration environment (like TestServer or WebSockets), which keeps your test execution fast and deterministic. You are essentially creating a "spy" that monitors the hub's interaction with the SignalR pipeline.

If your hub logic involves complex state—such as tracking users in groups or persisting connection IDs—this approach allows you to inject those dependencies into the hub constructor and verify that the Clients proxy is triggered exactly when the business logic dictates. This strategy bridges the gap between unit-testing the hub's internal methods and confirming that the real-time contract with the front-end remains intact.

Key Takeaway: To test SignalR hubs effectively, mock the IHubCallerClients and IClientProxy interfaces to verify that the hub correctly dispatches payloads to the expected target, bypassing the need for a live WebSocket connection.