Unittest SignalR Hubs

use*_*412 18 testing nunit unit-testing signalr

我想在SignalR中测试我的Hub,最好的方法是什么?

到目前为止我想到的可能的解决方案:

  • 创建一个可测试的Hub
  • 分离类的抽象逻辑
  • Selenium(想测试更小的单位)
  • 或者是一些SignalR测试功能被忽略了

目前使用SignalR 0.4和NUnit作为测试框架.

Bry*_*ong 8

链接显示如何使用Moq对SignalR集线器方法进行单元测试.您模拟了存储库,客户端,上下文和调用者.这是网站上的代码,我做了一些小改动,使其与最新的SignalR一起使用:

public class TestableChatHub : ChatHub  
{  
 public Mock<IChatRepository> MockChatRepository { get; private set; }

 public TestableChatHub(Mock<IChatRepository> mockChatRepository)  
   : base(mockChatRepository.Object)  
 {
   const string connectionId = "1234";  
   const string hubName = "Chat";  
   var mockConnection = new Mock<IConnection>();  
   var mockUser = new Mock<IPrincipal>();  
   var mockCookies = new Mock<IRequestCookieCollection>();

   var mockRequest = new Mock<IRequest>();  
   mockRequest.Setup(r => r.User).Returns(mockUser.Object);  
   mockRequest.Setup(r => r.Cookies).Returns(mockCookies.Object);

   Clients = new ClientProxy(mockConnection.Object, hubName);  
   Context = new HubCallerContext(mockRequest.Object, connectionId);

   var trackingDictionary = new TrackingDictionary();  
   Caller = new StatefulSignalProxy(
        mockConnection.Object, connectionId, hubName, trackingDictionary);  
 }  
} 
Run Code Online (Sandbox Code Playgroud)

然后该站点显示您可以使用此可测试集线器来编写单元测试:

   [TestClass]  
   public class ChatHubTests  
   {  
     private TestableChatHub _hub;

     public void SetUpTests()  
     {  
       _hub = GetTestableChatHub();  
     }

     [Test]  
     public void ExampleTest()  
     {  
       SetUpTests();
       const string message = "test";  
       const string connectionId = "1234";

       var result = _hub.Send(message);

       _hub.MockChatRepository.Verify(r => r.SaveMessage(message, connectionId));
       Assert.IsTrue(result);  
     }

     private TestableChatHub GetTestableChatHub()  
     {  
       var mockRepository = new Mock<IChatRepository>();  
       mockRepository.Setup(m => m.SaveMessage(
            It.IsAny<string>(), It.IsAny<string())).Returns(true);  
       return new TestableChatHub(mockRepository);  
     }  
   }  
Run Code Online (Sandbox Code Playgroud)

  • 第一条评论的新链接是:http://www.bradygaster.com/post/doing-bdd-with-signalr-and-jasmine (3认同)

lar*_*moa 5

使用几个巧妙的技巧创建单元测试SignalR集线器非常简单.需要注意的一点是SignalR使用了模拟dynamic框架可能不支持的类(我使用的是NSubstitute).

public class ProjectsHub: Hub
{
   public void AddProject(string id)
   {
      Clients.All.AddProject(id);
   }
}

[TestFixture]
public class ProjectsHubTests
{
    // Operations that clients might receive
    // This interface is in place in order to mock the
    // dynamic object used in SignalR
    public interface ISignals
    {
        void AddProject(string id);
    }

    [Test]
    public void AddProject_Broadcasts()
    {
        // Arrange
        ProjectsHub hub = new ProjectsHub();
        IHubCallerConnectionContext clients = 
                Substitute.For<IHubCallerConnectionContext>();
        ISignals signals = Substitute.For<ISignals>();
        SubstituteExtensions.Returns(clients.All, signals);
        hub.Clients = clients;

        // Act
        hub.AddProject("id");

        // Assert
        signals.Received(1).AddProject("id");
    }
}
Run Code Online (Sandbox Code Playgroud)

重写这个以使用例如Moq应该非常简单.


Bra*_*oor 4

这个问题是很久以前的问题了,但我还是会尽力回答。

如果您的实际集线器类中有很多逻辑,那么将逻辑抽象到单独的类中肯定是有意义的。我对 SignalR 支持的多人游戏演示也做了同样的事情。集线器类本身应该包含的唯一行为是与消息传递相关的行为。所有进一步的行动都应该被委托。

注意:这非常类似于 ASP .NET MVC 中的控制器设计指南:保持控制器较小并委派实际工作。

如果您希望使用 SignalR 进行集成测试,实际执行一些工作,selenium webdriver 将是一个不错的选择。但是您可能需要进行一些调整才能使 SignalR 消息传递在测试环境中完美运行。在谷歌上搜索“signalr selenium”(不带引号)以开始走上正确的轨道。

关于 SignalR 自动化测试的一些博文 =>这里这里