Подтвердить что ты не робот

Unittest SignalR Hubs

Я бы хотел проверить свой концентратор в SignalR, какой лучший подход?

Возможные решения, о которых я думал до сих пор:

  • Создать тестовый концентратор
  • Абстрактная логика для разделения класса
  • Селен (хотел бы испытать меньшие единицы)
  • Или некоторые функции тестирования SignalR упустили

В настоящее время используется SignalR 0.4 и NUnit в качестве среды тестирования.

4b9b3361

Ответ 1

Эта ссылка показывает, как unit test методы концентратора SignalR с использованием Moq. Вы макетируете репозиторий, клиенты, контекст и вызывающий. Здесь код с сайта, я внес некоторые незначительные изменения, чтобы заставить его работать с последним сигналом:

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);  
 }  
} 

Затем сайт показывает, что вы можете использовать этот тестовый концентратор для написания модульных тестов:

   [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);  
     }  
   }  

Ответ 2

Это довольно просто создать для unit test концентраторов 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");
    }
}

Переписывание этого для использования, например. Moq должен быть довольно простым.

Ответ 3

Этот вопрос с давних времен, но я сделаю все возможное, чтобы ответить в любом случае.

Если у вас много логики в вашем фактическом классе хаба, было бы разумно отвлечь логику к отдельному классу. Я сделал то же самое для моей многопользовательской демонстрации с поддержкой SignalR. Единственное поведение, которое должно пройти в вашем классе хаба, - это тот, который связан с обменом сообщениями. Все дальнейшие действия должны быть делегированы.

Примечание. Это очень похоже на рекомендации по дизайну контроллеров в ASP.NET MVC: не уменьшайте ваши контроллеры и делегируйте реальную работу.

Если вы хотите, чтобы интеграционные тесты с SignalR действительно выполняли определенную работу, селен-webdriver был бы хорошим вариантом. Но вам, вероятно, нужно будет немного подкорректировать, чтобы заставить Message SignRR работать отлично в контексте тестов. Сделайте поиск по Google для "signalr selenium" (без кавычек), чтобы начать работу на правильном пути.

Некоторые blogposts о автоматических тестах для SignalR = > здесь и здесь

Ответ 4

С SignalR 2.0 вы можете сделать это следующим образом:

// Arrange
var hub = new CodeInteractivePreviewHub();
var mockClients = new Mock<IHubCallerConnectionContext<dynamic>>();
hub.Clients = mockClients.Object;
dynamic all = new ExpandoObject();
mockClients.Setup(m => m.All).Returns((ExpandoObject)all);

// Act
var allSourceCodes = hub.InitiateCommunication(); //Change this line to your Hub method 

// Assert
Assert.IsNotNull(allSourceCodes);

Ответ 5

Это измененная версия ответа Iarsm для работы с XUnit и MOQ.

using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
using Moq;
using Xunit;

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

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);
    }

    [Fact]
    public void AddProject_Broadcasts() {
        // Arrange
        ProjectsHub hub = new ProjectsHub();
        var clients = new Mock<IHubCallerConnectionContext<dynamic>>();
        var signals = new Mock<ISignals>();
        hub.Clients = clients.Object;

        signals.Setup(m => m.AddProject(It.Is<string>(s => s == "id"))).Verifiable();
        clients.Setup(m => m.All).Returns(signals.Object);

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

        // Assert
        signals.VerifyAll();
    }
}

}