我有一个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);
}
}
}
我遇到了同样的问题。为了访问客户端列表以发送消息,将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);
}