我有一个想要进行单元测试的 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/