Asp.net core 带有HubContext的.net core 2.2信号器集线器单元测试问题

Asp.net core 带有HubContext的.net core 2.2信号器集线器单元测试问题,asp.net-core,moq,xunit,signalr-hub,Asp.net Core,Moq,Xunit,Signalr Hub,我有一个信号集线器,我希望进行单元测试。hub非常简单,只是它在ctor中包含一个IHubContext参数。我遇到的问题是,任何对UpdateData方法进行单元测试的尝试都会在出现空引用异常时失败,这样我就可以验证DataModel数据属性是否得到更新。到目前为止,我所能验证的只是该方法是否被调用。 是不是我没有正确模拟HubContext依赖关系 有人能提供如何解决这个问题的详细信息吗 using Microsoft.AspNetCore.SignalR; using Moq; using

我有一个信号集线器,我希望进行单元测试。hub非常简单,只是它在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);
        }

    }
}
使用Microsoft.AspNetCore.signal;
使用最小起订量;
使用系统线程;
使用System.Threading.Tasks;
使用Xunit;
命名空间测试
{
公共类数据模型
{
公共字符串名称{get;set;}
公共字符串作业{get;set;}
}
公共类数据集线器:集线器
{
私有只读IHubContext\u hubContext;
私有数据模型数据;
公共数据中心(IHubContext上下文)
{
_hubContext=上下文;
}
公共覆盖异步任务OnConnectedAsync()
{
wait Groups.AddToGroupAsync(Context.ConnectionId,“数据组”);
}
公共void UpdateData(数据模型更新)
{
数据=更新;
_hubContext.Clients.Group(“数据组”).SendAsync(“数据”,数据);
}
}
公共类DataHubTests
{
私有数据模型更新;
专用数据中心;
Mock mockClientProxy=new Mock();
Mock mockClients=new Mock();
Mock mockHubContext=new Mock();
Mock mockGroups=new Mock();
公共数据中心测试()
{
SetupData();
mockClients.Setup(clients=>clients.All).Returns(mockClientProxy.Object);
CancellationToken CancellationToken=默认值(CancellationToken);
mockGroups.Object.AddToGroupAsync(“1234”,“数据组”,cancellationToken);
mockHubContext.Setup(x=>x.Clients.All).Returns(mockClientProxy.Object);
Setup(groups=>groups.groups).Returns(mockGroups.Object);
hub=新的数据中心(mockHubContext.Object);
}
私有void SetupData()
{
更新=新数据模型();
update.Name=“Bob”;
update.Job=“Builder”;
}
[事实]
public void DataHubIsAThing()
{
Assert.NotNull(hub);
}
[事实]
public void updatedaitaiscaled()
{
//表演
hub.UpdateData(更新);
//断言
mockClients.Verify(clients=>clients.All,Times.one);
}
}
}

我也有同样的问题。IHubContext被注入到my Hub类的.ctor中,以便访问用于发送消息的客户端列表,但是在单元测试时,您必须模拟IHubContext,以便Signal在测试中工作

我的中心服务

公共MyHubService(IHubContext上下文,MyDbContext数据库) { _上下文=上下文; _db=db; } 我的集线器服务方法

公共异步任务发送通知(字符串消息)
{
wait_context.Clients.All.SendAsync(“通知”,消息);
}
我的单元测试

[事实]
公共异步任务SendNotification()
{
Mock mockClients=new Mock();
Mock mockClientProxy=new Mock();
mockClients.Setup(clients=>clients.All).Returns(mockClientProxy.Object);
var hubContext=newmock();
Setup(x=>x.Clients).返回(()=>mockClients.Object);
var db=MyDBMock.GetMock();
MyHubService hub=新的MyHubService(hubContext.Object,db);
等待hub.SendNotification(“哟!这是单元测试。”);
mockClients.Verify(clients=>clients.All,Times.one);
}

我也有同样的问题。IHubContext被注入到my Hub类的.ctor中,以便访问用于发送消息的客户端列表,但是在单元测试时,您必须模拟IHubContext,以便Signal在测试中工作

我的中心服务

公共MyHubService(IHubContext上下文,MyDbContext数据库) { _上下文=上下文; _db=db; } 我的集线器服务方法

公共异步任务发送通知(字符串消息)
{
wait_context.Clients.All.SendAsync(“通知”,消息);
}
我的单元测试

[事实]
公共异步任务SendNotification()
{
Mock mockClients=new Mock();
Mock mockClientProxy=new Mock();
mockClients.Setup(clients=>clients.All).Returns(mockClientProxy.Object);
var hubContext=newmock();
Setup(x=>x.Clients).返回(()=>mockClients.Object);
var db=MyDBMock.GetMock();
MyHubService hub=新的MyHubService(hubContext.Object,db);
等待hub.SendNotification(“哟!这是单元测试。”);
mockClients.Verify(clients=>clients.All,Times.one);
}

对于.NET Core v3.0,通过一些自定义的组输入/输出方法,我使用了以下方法:

公共类MyHubTests
{
私人MyHub MyHub;
私有Mock mockClients=new Mock();
私有Mock mockGroups=new Mock();
私有Mock mockClientProxy=new Mock();
私有Mock mockContext=new Mock();
私有列表groupIds=新列表()
{//***注意:从技术上讲,这些都不是确定性的***
Guid.NewGuid().ToString(),
Guid.NewGuid().ToString(),
};
私有列表clientId=新列表(){“0”、“1”、“2”};
[测试初始化]
公共作废设置()
{
mockClients.Setup(client=>client.All).Returns(mockClientProxy.Object);
mockClients.Setup(client=>client.OthersInGroup(It.IsIn(groupIds))).Returns(mockClientProxy.Object);
mockGroups.Setup(group=>group.AddToGroupAsync(It.IsIn(clientId),It.IsIn(groupId),new System.Threading.CancellationToken())。返回(Task.FromResult(true));
mockGroups.Setup(group=>group.RemoveFromGroupAsync(It.IsIn(clientid)),It.I