Unittest SignalR Hubs
Я бы хотел проверить свой концентратор в SignalR, какой лучший подход?
Возможные решения, о которых я думал до сих пор:
- Создать тестовый концентратор
- Абстрактная логика для разделения класса
- Селен (хотел бы испытать меньшие единицы)
- Или некоторые функции тестирования SignalR упустили
В настоящее время используется SignalR 0.4 и NUnit в качестве среды тестирования.
Ответы
Ответ 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();
}
}
}
Ответ 6
Я лично считаю, что лучший способ - это дать http://www.asp.net/signalr/overview/testing-and-debugging/unit-testing-signalr-applications