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.