Search code examples
c#.netsignalrxunit

How to write integration test for SignalR


I use Signalr in my Web API. How to perform integration testing on it? I do not want to mock Hub I want to work on real instance of connection and check the results.

Currently I have something like this. I can not establish connection to my hub

[Fact]
 public async Task Should_CreateUser()
 {
     using var client = new WebApplicationFactory<Program>().CreateClient();

     var handler = new HttpClientHandler();
     handler.ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
     var connection = new HubConnectionBuilder()
         .WithUrl(client.BaseAddress + "/auction-hub", options =>
         {
             options.HttpMessageHandlerFactory = _ => handler;
         })
         .Build();

     await connection.StartAsync();

 }

Hub:

namespace Bidnest.Application.Hubs
{
    public class AuctionHub : Hub<IAuctionHub>
    {

        public override async Task OnConnectedAsync()
        {
            await Clients.All.UserWasOutbid($"Hey {Context.UserIdentifier}");
        }
    }
}

Solution

  • My solution:

    public class UserEventsTest : BaseIntegrationTest
    {
        private readonly IntegrationTestWebAppFactory _factory;
    
        public UserEventsTest(IntegrationTestWebAppFactory factory) : base(factory)
        {
            _factory = factory;
        }
    
        [Fact]
        public async Task Should_CreateUser()
        {
            var client = _factory.CreateClient();
            var server = _factory.Server;
            var result = await client.GetAsync("/WeatherForecast");
            result.EnsureSuccessStatusCode();
    
            var connection = new HubConnectionBuilder()
                .WithUrl("wss://localhost" + "/auction-hub", options =>
                {
                    options.HttpMessageHandlerFactory = _ => server.CreateHandler();
                })
                .Build();
    
            await connection.StartAsync();
    
        }
    }
    

    This line use IntegrationTestWebAppFactory

    var client = _factory.CreateClient();
    

    which is an abstraction of

    new WebApplicationFactory<Program>().CreateClient()
    

    So if you do not need abstraction you can go with this approach. It creates application and expose endpoints.

    Here I make sure standard HTTP requests are fine

    var result = await client.GetAsync("/WeatherForecast");
    result.EnsureSuccessStatusCode();
    

    And here I connect to my hub mapped in Program.cs

    var connection = new HubConnectionBuilder()
                .WithUrl("wss://localhost" + "/auction-hub", options =>
                {
                    options.HttpMessageHandlerFactory = _ => server.CreateHandler();
                })
                .Build();
    
            await connection.StartAsync();