对于仍在为此苦苦挣扎的人,您实际上可以在 NSubsitute 中模拟动态,它只需要跳过一些小圈子。请参阅以下模拟对 signalR 客户端集线器的调用的案例。
重要的一行是这一行:
SubstituteExtensions.Returns(_hubContext.Clients.All, _mockClient);
为了模拟动态,我创建了一个带有我想要监听的方法的接口。然后,您需要使用 SubstituteExtensions.Returns 而不是简单地将 .Returns 链接到对象的末尾。
如果您不需要验证任何内容,您也可以使用匿名对象。
完整的代码示例如下:
[TestFixture]
public class FooHubFixture
{
private IConnectionManager _connectionManager;
private IHubContext _hubContext;
private IMockClient _mockClient;
[SetUp]
public void SetUp()
{
_hubContext = Substitute.For<IHubContext>();
_connectionManager = Substitute.For<IConnectionManager>();
_connectionManager.GetHubContext<FooHub>().Returns(_hubContext);
_mockClient = Substitute.For<IMockClient>();
SubstituteExtensions.Returns(_hubContext.Clients.All, _mockClient);
}
[Test]
public void PushFooUpdateToHub_CallsUpdateFooOnHubClients()
{
var fooDto = new FooDto();
var hub = new FooHub(_connectionManager);
hub.PushFooUpdateToHub(fooDto);
_mockClient.Received().updateFoo(fooDto);
}
public interface IMockClient
{
void updateFoo(object val);
}
}
public class FooHub : Hub
{
private readonly IConnectionManager _connectionManager;
public FooHub(IConnectionManager connectionManager)
{
_connectionManager = connectionManager;
}
public void PushFooUpdateToHub(FooDto fooDto)
{
var context = _connectionManager.GetHubContext<FooHub>();
context.Clients.All.updateFoo(fooDto);
}
}