C# 我应该如何在控制器中模拟SignalR HubContext进行单元测试?
我正在MVC5项目中使用信号器。我在控制器内进行如下呼叫:C# 我应该如何在控制器中模拟SignalR HubContext进行单元测试?,c#,unit-testing,signalr,moq,asp.net-mvc-5,C#,Unit Testing,Signalr,Moq,Asp.net Mvc 5,我正在MVC5项目中使用信号器。我在控制器内进行如下呼叫: private Microsoft.AspNet.SignalR.IHubContext blogHubContext = Microsoft.AspNet.SignalR.GlobalHost.ConnectionManager.GetHubContext<BlogHub>(); blogHubContext.Clients.All.addNewBlogToPage(RenderPartialViewToString("B
private Microsoft.AspNet.SignalR.IHubContext blogHubContext = Microsoft.AspNet.SignalR.GlobalHost.ConnectionManager.GetHubContext<BlogHub>();
blogHubContext.Clients.All.addNewBlogToPage(RenderPartialViewToString("Blog", model));
private Microsoft.AspNet.signal.IHubContext blogHubContext=Microsoft.AspNet.signal.GlobalHost.ConnectionManager.GetHubContext();
blogHubContext.Clients.All.addNewBlogToPage(renderPartialViewToSturing(“Blog”,model));
我正在尝试在此控制器内对操作进行单元测试。在我添加信号器功能之前,单元测试一直运行良好。现在,我正试图弄清楚如何模拟Hubbon的上下文。我有两种可能
private Microsoft.AspNet.SignalR.IHubContext blogHubContext;
public BlogController(Microsoft.AspNet.SignalR.IHubContext topicHub = null){
blogHubContext = (blogHub != null) ? blogHub : Microsoft.AspNet.SignalR.GlobalHost.ConnectionManager.GetHubContext<BlogHub>();
}
私有Microsoft.AspNet.signal.IHubContext blogHubContext;
公共BlogController(Microsoft.AspNet.signal.IHubContext topicHub=null){
blogHubContext=(blogHub!=null)?blogHub:Microsoft.AspNet.signar.GlobalHost.ConnectionManager.GetHubContext();
}
然后,当我在单元测试中创建HubContext时,我可以以某种方式模拟它并将其发送给控制器。但到目前为止,我只有以下几点:
Mock<IHubContext> blogHub = new Mock<IHubContext>();
Mock blogHub=new Mock();
(注意:我简化了所有内容,只关注信号器方面的内容。控制器中还使用了存储库等)感谢您的指导。或者这两种方法都可以接受?谢谢。更新,请查看此代码,我基于默认的MVC模板。不需要包装器类
public class HomeController : Controller
{
private readonly IHomeHub _hub;
public HomeController(IHomeHub hub)
{
_hub = hub;
}
public ActionResult Index()
{
_hub.Hello();
return View();
}
}
public interface IHomeHub
{
void Hello();
}
public class HomeHub : Hub, IHomeHub
{
public void Hello()
{
Clients.All.hello();
}
}
对于单元测试:
[TestMethod]
public void Index()
{
var mockHub = new Mock<IHomeHub>();
// Arrange
HomeController controller = new HomeController(mockHub.Object);
// Act
ViewResult result = controller.Index() as ViewResult;
// Assert
Assert.IsNotNull(result);
mockHub.Verify(h=>h.Hello(), Times.Once);
}
[TestMethod]
公共空间索引()
{
var mockHub=new Mock();
//安排
HomeController=新的HomeController(mockHub.Object);
//表演
ViewResult=controller.Index()作为ViewResult;
//断言
Assert.IsNotNull(结果);
验证(h=>h.Hello(),Times.Once);
}
我更喜欢第一个选项,因为您不需要另一层包装类,因为它不添加任何功能。@AD.Net谢谢。在这种情况下,我有什么想法可以去模仿我正在使用的功能中心。我一直在努力想如何做到这一点,这让我想到了第二个选择。你对嘲弄熟悉吗?模拟信号集线器似乎和模拟其他任何东西一样。@BenAaronson由于addNewBlogToPage函数实际上是一个由信号器调用的JS函数,我不知道如何模拟它。不过,现在就按照AD.Net的建议去做,可能会把事情重新安排到一个更好的结构中。@AndrewPolland,js函数将基于你的.Net代码,所以它对js代理的生成不会有多大影响。这看起来非常好。但我无法让它工作,因为只有在函数是静态的情况下才能从集线器(在控制器内)调用函数,而从接口实现时就不能。我的理解是这样的。抱歉,不清楚,方法Hello在Hub类上不是静态的,您可以从控制器调用它。抱歉,部分问题是我的目的。静电并不像我想的那样需要。但是,当从控制器调用方法Hello时,无法按您的方式调用客户机。它会产生以下错误:不支持使用不是由HubPipeline创建的Hub实例。我已对您的答案进行了编辑,以便它能够正常工作。希望您同意。抱歉,编辑被拒绝。但本质上不是客户端。All.hello();我必须使用var hubContext=GlobalHost.ConnectionManager.GetHubContext();hubContext.Clients.All.hello();