Moq可以模拟HubConnection,但RhinoMocks不能

本文关键字:RhinoMocks 不能 HubConnection 模拟 Moq | 更新日期: 2023-09-27 18:13:16

我正在查看SignalR的单元测试,并注意到其中一个测试使用Moq创建模拟HubConnection:

[Fact]
public void HubCallbackClearedOnFailedInvocation()
{
    var connection = new Mock<HubConnection>("http://foo");
    var tcs = new TaskCompletionSource<object>();
    tcs.TrySetCanceled();
    connection.Setup(c => c.Send(It.IsAny<string>())).Returns(tcs.Task);
    var hubProxy = new HubProxy(connection.Object, "foo");
    var aggEx = Assert.Throws<AggregateException>(() => { hubProxy.Invoke("foo", "arg1").Wait(); });
    var ex = aggEx.Unwrap();
    Assert.IsType(typeof(TaskCanceledException), ex);
    Assert.Equal(connection.Object._callbacks.Count, 0);
}

然而,当我尝试用一个稍微不同的mock框架(RhinoMocks)做同样的事情时,它抱怨该方法不是虚拟的:

[Test]
public void ShouldCreateBrokerWithHubConnection()
{
    //Arrange
    var url = "http://localhost6790";
    var hubProxy = MockRepository.GenerateMock<IHubProxy>();
    var hubConnection = MockRepository.GenerateMock<HubConnection>(url);
    hubConnection.(c => c.CreateHubProxy("ArtemisClientHub")).Return(hubProxy);
    ... (more code)
 }

System.InvalidOperationException : Invalid call, the last call has been used or no call has been made (make sure that you are calling a virtual (C#) / Overridable (VB) method).

这只是RhinoMocks与Moq这样的新库相比的一个缺点吗?

Moq可以模拟HubConnection,但RhinoMocks不能

我的建议是使用代码中的非具体类型,并使用Ioc注入具体类型。然而,与服务器不同,signalr . net客户端缺少一个DependencyResolver。我用自己的方法来解决这个问题,你可以在这里查看代码(但在你的情况下,你可以使用任何Ioc,如Ninject, autoface等)

https://github.com/AndersMalmgren/SignalR.EventAggregatorProxy/blob/master/SignalR.EventAggregatorProxy.Client.DotNet/Bootstrap/DependencyResolver.cs

集线器连接和代理有点难以抽象,因为您依赖于创建代理的具体类型。我通过将hub代理的创建抽象为一个工厂接口来解决这个问题,该接口返回一个可以轻松模拟的IHubProxy。

看这里https://github.com/AndersMalmgren/SignalR.EventAggregatorProxy/blob/master/SignalR.EventAggregatorProxy.Client.DotNet/Bootstrap/Factories/HubProxyFactory.cs

所有的例子都取自我的。net客户端为这个库https://github.com/AndersMalmgren/SignalR.EventAggregatorProxy