带有HubContext的.net核心测试2.2 SignalR集线器问题

问题描述 投票:0回答:1

我有一个SignalR集线器,希望对其进行单元测试。该集线器非常简单,只是它在ctor中包含IHubContext参数。我遇到的问题是,对单元测试UpdateData方法进行任何尝试,以便我可以验证DataModel数据属性是否已更新,都将在null引用异常上失败。到目前为止,我只能验证是否调用了该方法。是否没有正确模拟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);
        }

    }
}
asp.net-core moq xunit signalr-hub
1个回答
0
投票

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

我的中心服务.ctor

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

我的集线器服务方法

    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 db = MyDBMock.GetMock();

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

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

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

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

        }
© www.soinside.com 2019 - 2024. All rights reserved.