Skip to content

How to unit test ServerlessHub #2818

Open

Description

What version of .NET does your existing project use?

.NET 6

What version of .NET are you attempting to target?

.NET 8

Description

After the migration to .NET 8, in order to use SignalR with Azure Functions, it's required to inherit from ServerlessHub. This is no longer unit testable or at least I couldn't find a way to do so.

Here's an example code that I want to unit test.

using DT.Common.Enums.WebSocket;
using DT.Host.Common.Contract.LocalAuthentication;
using DT.Host.SignalRProcessor.Contract;
using Microsoft.Extensions.Logging;
using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.SignalRService;
using Microsoft.AspNetCore.SignalR;
using Newtonsoft.Json;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Http;
using FromBodyAttribute = Microsoft.Azure.Functions.Worker.Http.FromBodyAttribute;
using System.Diagnostics.CodeAnalysis;

namespace DT.Host.SignalRProcessor.Functions
{
    [SignalRConnection("ConnectionStrings:SignalR")]
    [ExcludeFromCodeCoverage]
    public class SignalRMessageProcessor : ServerlessHub
    {
        private const string HubName = "digitaltrust";

        private readonly IAuthenticationManager _authenticationManager;
        private readonly ILogger<SignalRMessageProcessor> _logger;

        public SignalRMessageProcessor(
            IServiceProvider serviceProvider,
            IAuthenticationManager authenticationManager,
            ILogger<SignalRMessageProcessor> logger) : base(serviceProvider)
        {
            _authenticationManager = authenticationManager;
            _logger = logger;
        }

        [Function("negotiate")]
        public async Task<IActionResult> Negotiate(
            [HttpTrigger("get", Route = "negotiate/{userId}")] HttpRequest req,
            string userId)
        {
            var statusCode = Authenticate(req);
            if (statusCode != StatusCodes.Status200OK)
            {
                return new StatusCodeResult(statusCode);
            }
            _logger.LogInformation($"userId: {userId}; Negotiate Function triggered");

            var negotiateResponse = await NegotiateAsync(new() { UserId = userId });
            
            var response = JsonConvert.DeserializeObject<SignalRConnectionInfo>(negotiateResponse.ToString());

            return new OkObjectResult(response);
        }

        private int Authenticate(HttpRequest req)
        {
            req.Headers.TryGetValue("Authorization", out var authHeader);
            if (authHeader.FirstOrDefault() is null)
            {
                return StatusCodes.Status403Forbidden;
            }
            var token = authHeader.First().Trim();
            if (token.StartsWith("basic", StringComparison.OrdinalIgnoreCase))
            {
                try
                {
                    _authenticationManager.Authenticate(token);
                    return StatusCodes.Status200OK;
                }
                catch (UnauthorizedAccessException)
                {
                    return StatusCodes.Status401Unauthorized;
                }

            }
            return StatusCodes.Status401Unauthorized;
        }
}

Any guidance on this is appreciated. I tried mocking IServiceProvider with no luck.

Project configuration and dependencies

No response

Link to a repository that reproduces the issue

No response

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions