سؤال

See this code:

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();

Note that DoSomething is a non-virtual methodcall in an autogenerated class which inherits from NO interface. So it shouldn't work, according to common knowledge. But it does.

Problem is that it's the only (non commercial) framework that can do this:

  • Rhino.Mocks works, and verification works too
  • FakeItEasy says it doesn't find a default constructor (probably just wrong exception message): No default constructor was found on the type SomeNamespace.TicketStoreService
  • Moq gives something sane and understandable: Invalid setup on a non-virtual (overridable in VB) member: service=> service.DoSomething
  • Nsubstitute gives a message System.NotSupportedException: Cannot serialize member System.ComponentModel.Component.Site of type System.ComponentModel.ISite because it is an interface.

I'm really wondering what's going on here with the frameworks, except Moq. The "fancy new" frameworks seem to have an initial perf hit too, probably preparing some Type cache and serializing stuff, whilst RhinoMocks somehow manages to create a very "slim" mock without recursion. I have to admit I didn't like RhinoMocks very well, but here it shines.. unfortunately.

So, is there a way to get that to work with newer (non-commercial!) mocking frameworks, or somehow get a sane error message (describing which of the 6 parameters I actually use was different in which way) out of Rhino.Mocks? And why can Rhino.Mocks achieve this, when clearly every Mocking framework states it can only work with virtual methods when given a concrete class?

*Let's not derail the discussion by talking about alternative approaches like Extract&Override or runtime-proxy Mocking frameworks like JustMock/TypeMock/Moles or the new Fakes framework, I know these, but that would be less ideal solutions, for reasons beyond this topic.

هل كانت مفيدة؟

المحلول

You could try the Fody plugin Virtuosity which makes all members virtual using il weaving, so any dynamic proxy-based library will be able to work with it. Check the Fody example for what's involved hooking this up.

As to why Rhino Mocks works, I couldn't get it to:

[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; }
}

It fails with:

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)

It looks like there is something else happening here. Are you able to post a stand-alone, minimal case that reproduces this?

Lastly, all the libraries you mentioned are open source, so it would be great to pick the one you like most and see if you can improve the error messages or performance. If you haven't contributed to open source before it can seem a bit daunting, but people on the projects are normally only too happy to try and help out anyone interesting in contributing. :)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top