use*_*412 18 testing nunit unit-testing signalr
我想在SignalR中测试我的Hub,最好的方法是什么?
到目前为止我想到的可能的解决方案:
目前使用SignalR 0.4和NUnit作为测试框架.
此链接显示如何使用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)
使用几个巧妙的技巧创建单元测试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应该非常简单.
这个问题是很久以前的问题了,但我还是会尽力回答。
如果您的实际集线器类中有很多逻辑,那么将逻辑抽象到单独的类中肯定是有意义的。我对 SignalR 支持的多人游戏演示也做了同样的事情。集线器类本身应该包含的唯一行为是与消息传递相关的行为。所有进一步的行动都应该被委托。
注意:这非常类似于 ASP .NET MVC 中的控制器设计指南:保持控制器较小并委派实际工作。
如果您希望使用 SignalR 进行集成测试,实际执行一些工作,selenium webdriver 将是一个不错的选择。但是您可能需要进行一些调整才能使 SignalR 消息传递在测试环境中完美运行。在谷歌上搜索“signalr selenium”(不带引号)以开始走上正确的轨道。
| 归档时间: |
|
| 查看次数: |
8939 次 |
| 最近记录: |