我正在为我的SignalR集线器编写单元测试,并使用SignalR .NET客户端(版本2.3.0)进行测试,但是当当前连接被排除在外时,我无法获得其他连接来接收广播。广播。
集线器方法正在这样广播:
Clients.Group(groupName, Context.ConnectionId).sendMessage("A message");
我的测试被配置为与集线器有2个连接,每个连接将调用集线器方法,该方法会将连接放入groupName
。然后,我有一个HubConnection.On
事件来处理hub方法进行的广播,然后将其结果用于声明测试。在代码中可能更清楚地解释了这一点(为简便起见,我删除了一些AddBroadcast重载):
/// <summary>
/// Class to handle the connection, calling of methods and broadcast for a SignalR hub
/// </summary>
public class HubManager
{
public enum Froms
{
Other1,
Other2
}
private HubConnection hubConnection = null;
private IHubProxy hub = null;
/// <summary>
/// The outcome of the broadcast that is made
/// </summary>
public object Result { get; private set; } = null;
/// <summary>
/// The connection ID of this hub connection
/// </summary>
public string ConnectionID { get { return this.hubConnection.ConnectionId; } }
public HubManager(string h)
{
//Create the SignalR connection
this.hubConnection = new HubConnection("http://mywebsite.com");
//Gain access to the hub
this.hub = hubConnection.CreateHubProxy(h);
//Start the connection up and wait for it to complete
this.hubConnection.Start()
.ContinueWith(task =>
{
if (task.IsFaulted)
{
throw new Exception($"Error opening the hub connection ({h}): {task.Exception.GetBaseException()}");
}
})
.Wait();
}
/// <summary>
/// Broadcast a message to clients
/// </summary>
/// <param name="methodName">The name of broadcast message</param>
public void AddBroadcast(string methodName)
{
this.hub.On(methodName, () => {
this.Result = methodName;
});
}
/// <summary>
/// Broadcast a message to clients
/// </summary>
/// <param name="methodName">The name of broadcast message</param>
public void AddBroadcast<T>(string methodName)
{
this.hub.On<T>(methodName, _1 => {
this.Result = _1;
});
}
/// <summary>
/// Invokes a specific hub method
/// </summary>
/// <param name="methodName">The name of the hub method to invoke</param>
/// <param name="args">The parameters for the method</param>
public void CallMethod(string methodName, params object[] args)
{
this.hub.Invoke(methodName, args)
.ContinueWith(task =>
{
if (task.IsFaulted)
{
throw new Exception($"Error calling hub method {methodName}: {task.Exception.GetBaseException()}");
}
})
.Wait();
}
}
使用案例:
//Create a dictionary to hold the connections
var hubManagers = new Dictionary<HubManager.Froms, HubManager>();
hubManagers.Add(HubManager.Froms.Other1, new HubManager(hubName));
hubManagers.Add(HubManager.Froms.Other2, new HubManager(hubName));
//Call HubMethod1 which will add the connection to the same group
hubManagers[HubManager.Froms.Other1].CallMethod("HubMethod1", user1ID);
hubManagers[HubManager.Froms.Other2].CallMethod("HubMethod1", user2ID);
//Set a broadcast handle for the second connection (Other2)
hubManagers[HubManager.Froms.Other2].AddBroadcast<string, string>("callbackMethod");
//Make a hub method call (from Other1) to cause the callbackMethod to run
//As from above, the Other1 connection should not receive it but Other2 should
hubManagers[HubManager.Froms.Other1].CallMethod("HubMethod2", user1ID);
//Get the broadcast result for the second connection (Other2)
var result = hubManagers[HubManager.Froms.Other2].Result;
//result == null
[我尝试在以下组合上使用AdddBroadcast
,并且每种情况都导致result
为空:Other1
,Other2
和Other1
&Other2
。
如果更改Clients.Group(groupName, Context.ConnectionId).sendMessage("A message");
以不排除当前连接(Clients.Group(groupName).sendMessage("A message");
),并且在AddBroadcast
上使用Other2
,则result
包含期望值。
[该过程在实时系统(使用ASP.NET和JavaScript)上按预期方式工作,在该系统中不会向调用连接发送sendMessage
,但向该组的其他成员发送了此连接。
非常欢迎在广播中排除第一个连接时,如何使第二个SignalR .NET客户端连接接收广播的任何想法!
[一段时间后,我意识到this.hub.On
事件正在触发,但是在调用获取结果(var result = hubManagers[HubManager.Froms.Other2].Result;
)之后。因此,我添加了一种粗略的等待方法(我不为之感到骄傲!),并且做到了。
新方法: