asp.net-core - HubContext的单元测试.net core 2.2 SignalR集线器问题

标签 asp.net-core moq xunit signalr-hub

我有一个想要进行单元测试的 SignalR 集线器。集线器非常简单,只是它在 ctor 中包含一个 IHubContext 参数。我遇到的问题是,任何对 UpdateData 方法进行单元测试以便我可以验证 DataModel 数据属性是否已更新的尝试都会在空引用异常上失败。到目前为止,我只能验证该方法是否被调用。 是不是我没有正确模拟 HubContext 依赖?

谁能详细说明如何解决这个问题?

using Microsoft.AspNetCore.SignalR;
using Moq;
using System.Threading;
using System.Threading.Tasks;
using Xunit;

namespace Tests
{
    public class DataModel
    {
        public string Name { get; set; }
        public string Job { get; set; }

    }

    public class DataHub : Hub
    {
        private readonly IHubContext<DataHub> _hubContext;

        private DataModel data;

        public DataHub(IHubContext<DataHub> context)
        {
            _hubContext = context;
        }

        public override async Task OnConnectedAsync()
        {
            await Groups.AddToGroupAsync(Context.ConnectionId, "DataGroup");
        }

        public void UpdateData(DataModel update)
        {
            data = update;
            _hubContext.Clients.Group("DataGroup").SendAsync("Data", data);
        }

    }

    public class DataHubTests
    {

        private DataModel update;
        private DataHub hub;

        Mock<IClientProxy> mockClientProxy = new Mock<IClientProxy>();
        Mock<IHubClients> mockClients = new Mock<IHubClients>();
        Mock<IHubContext<DataHub>> mockHubContext = new Mock<IHubContext<DataHub>>();
        Mock<IGroupManager> mockGroups = new Mock<IGroupManager>();

        public DataHubTests()
        {
            SetupData();

            mockClients.Setup(clients => clients.All).Returns(mockClientProxy.Object);

            CancellationToken cancellationToken = default(CancellationToken);
            mockGroups.Object.AddToGroupAsync("1234", "DataGroup", cancellationToken);

            mockHubContext.Setup(x => x.Clients.All).Returns(mockClientProxy.Object);            
            mockHubContext.Setup(groups => groups.Groups).Returns(mockGroups.Object);

            hub = new DataHub(mockHubContext.Object);


        }

        private void SetupData()
        {
            update = new DataModel();
            update.Name = "Bob";
            update.Job = "Builder";
        }

        [Fact]
        public void DataHubIsAThing()
        {
            Assert.NotNull(hub);
        }

        [Fact]        
        public void UpdateDataIsCalled()
        {
            // act
            hub.UpdateData(update);
            // assert
            mockClients.Verify(clients => clients.All, Times.Once);
        }

    }
}

最佳答案

我遇到了同样的问题。 IHubContext 被注入(inject)到我的 Hub 类的 .ctor 中,以便访问客户端列表以发送消息,但是在单元测试时,您必须模拟 IHubContext 以便 SignalR 在测试中工作。

我的 Hub 服务 .ctor

public MyHubService(IHubContext<MyHubService> context, MyDbContext db)
{
    _context = context;
    _db = db;
}

我的 Hub 服务方法

public async Task SendNotification(string message)
{
    await _context.Clients.All.SendAsync("Notification", message);
}

我的单元测试

[Fact]
public async Task SendNotification()
{
    Mock<IHubClients> mockClients = new Mock<IHubClients>();
    Mock<IClientProxy> mockClientProxy = new Mock<IClientProxy>();
    mockClients.Setup(clients => clients.All).Returns(mockClientProxy.Object);

    var hubContext = new Mock<IHubContext<MyHubService>>();
    hubContext.Setup(x => x.Clients).Returns(() => mockClients.Object);

    var db = MyDBMock.GetMock();
    MyHubService hub = new MyHubService(hubContext.Object, db);

    await hub.SendNotification("Yo! This is the unit test.");

    mockClients.Verify(clients => clients.All, Times.Once);
}

关于asp.net-core - HubContext的单元测试.net core 2.2 SignalR集线器问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57577371/

相关文章:

c# - 整洁架构和 Asp.Net 核心标识

c# - Asp.Net Core 3.1 Appsettings 不尊重 JsonConverter

c# - 如果我们不通过单元测试验证私有(private)方法是否被调用,我们如何验证它们是否被调用?

nunit - 运行长时间运行的 NUnit/xUnit 测试,这样它们就不会阻塞其他测试

java - Surefire - 排除测试目录

unit-testing - Autofixture 和 WebApi Controller

c# - 使用 Github Actions 将多项目 ASP.NET Core Web 应用部署到 Azure 应用服务

c# - 将嵌套对象发送到asp.net core Get方法

c# - 在 ASP.NET MVC Controller 中进行 setter 注入(inject)时如何传递模拟对象

TDD 系统被测创建模式(AutoFixture)