【问题标题】:generated service mock: everything but RhinoMocks fails?生成的服务模拟:除了 RhinoMocks 之外的一切都失败了?
【发布时间】:2012-06-26 08:53:23
【问题描述】:

查看此代码:

TicketStoreService fakeTicketStoreService = 
                                        MockRepository.GenerateMock<TicketStoreService>(); 

fakeTicketStoreService.Expect(service => service.DoSomething(Arg.Is(new Guid()))
                      .Return(new Guid());

fakeTicketStoreService.DoSomething(Arg.Is(new Guid()));
fakeTicketStoreService.VerifyAllExpectations();

请注意,DoSomething 是自动生成的类中的非虚拟方法调用,它继承自 NO 接口。因此,根据常识,它不应该工作。 但确实如此。

问题是它是唯一可以做到这一点的(非商业)框架:

  • Rhino.Mocks 有效,验证也有效
  • FakeItEasy 说它没有找到默认构造函数(可能只是错误的异常消息):No default constructor was found on the type SomeNamespace.TicketStoreService
  • 起订量给出了一些理智和可以理解的东西:Invalid setup on a non-virtual (overridable in VB) member: service=&gt; service.DoSomething
  • Nsubstitute 给消息System.NotSupportedException: Cannot serialize member System.ComponentModel.Component.Site of type System.ComponentModel.ISite because it is an interface.

我真的很想知道除了最小起订量之外的框架是怎么回事。 “花哨的新”框架似乎也有一个初步的性能命中,可能准备了一些类型缓存和序列化的东西,而 RhinoMocks 不知何故设法创建了一个非常“苗条”的模拟而没有递归。我不得不承认我不太喜欢 RhinoMocks,但它在这里闪耀……不幸的是。

那么,有没有办法让它与更新的(非商业!)模拟框架一起工作,或者以某种方式得到一个理智的错误消息(描述我实际使用的 6 个参数中的哪一个是不同的? ) 出 Rhino.Mocks?为什么 Rhino.Mocks 可以做到这一点,而每个 Mocking 框架都明确表示它只能在给定具体类的情况下使用虚拟方法?

*我们不要通过讨论诸如 Extract&Override 之类的替代方法或 JustMock/TypeMock/Moles 之类的运行时代理 Mocking 框架或新的 Fakes 框架来破坏讨论,我知道这些,但由于除此之外的原因,这不是理想的解决方案主题。

【问题讨论】:

  • MockRepository 返回 Mock?如果是起订量?
  • @Anton no, Mock,因为 TicketStoreService 是一个生成的服务,没有从接口派生.. mock 的行为是可以理解的,问题是:为什么 RhinoMocks 工作,为什么不能其他框架可以吗?

标签: mocking moq rhino-mocks fakeiteasy nsubstitute


【解决方案1】:

您可以尝试使用 Fody 插件 Virtuosity,它使用 il weaving 使所有成员虚拟化,因此任何基于动态代理的库都可以使用它。查看Fody example 了解相关内容。

至于 Rhino Mocks 为何有效,我无法理解:

[Test]
public void FieldTest() {
    var fakeTicketStoreService = MockRepository.GenerateMock<TicketStoreService>(); 
    fakeTicketStoreService.Expect(service => service.DoSomething(Arg.Is(new Guid()))).Return(new Guid());
    fakeTicketStoreService.DoSomething(Arg.Is(new Guid()));
    fakeTicketStoreService.VerifyAllExpectations();
}

public class TicketStoreService {
    public Guid DoSomething(Guid guid) { return guid; }
}

它失败了:

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).
   at Rhino.Mocks.LastCall.GetOptions()
   at Rhino.Mocks.RhinoMocksExtensions.Expect(T mock, Function`2 action)

这里似乎发生了其他事情。你能发布一个独立的、最小的案例来重现这个吗?

最后,您提到的所有库都是开源的,因此最好选择您最喜欢的库,看看您是否可以改进错误消息或性能。如果您在看起来有点令人生畏之前还没有为开源做出过贡献,但是项目中的人们通常非常乐意尝试帮助任何有兴趣做出贡献的人。 :)

【讨论】:

  • 好答案,很遗憾我现在无法将其标记为正确,因为它没有回答为什么 RhinoMocks 在那里工作的问题,但 Fody 看起来很好,我认为我没有找到新的东西在这里。我使用封装服务调用的包装器解决了这个问题,无论如何都更干净(NSubstitute 错误消息>> RhinoMocks 错误消息),但当然+1,并且一旦我确定没有其他人加入就接受答案;)
  • 我很高兴了解为什么 Rhino Mocks 适用于您的案例,但您需要发布一个可运行的示例,因为我无法重现它。 :)
  • 当我有时间的时候我会尝试这样做,不幸的是服务类本身是一个非常大的部分类,所以我不得不逐步剥离它......再次,会做一次我找时间。 :)
猜你喜欢
  • 2015-05-09
  • 2014-01-03
  • 1970-01-01
  • 1970-01-01
  • 2015-01-14
  • 2011-03-19
  • 1970-01-01
  • 2017-07-02
  • 1970-01-01
相关资源
最近更新 更多