Ever attempted to mock any of the following:
What all those points have in common? They share similar problem - you cannot do that. Why is that so? To explain why such limitation is present on all of the most popular mocking frameworks, first we need to understand how exactly they work.
Under the hood
Luckily, this isn't too complicated. What your mocking framework does when you call
new Mock<IUserRepository>() is creation of new type, a type that will implement
IUserRepository interface (or derive from mocked base class). Naturally, it doesn't create any new source files, compile code and magically "put" new types into your assembly. Instead, mocking framework creates new, dynamic assembly (generated in runtime) and creates new type implementing your interface (also generated in runtime) which resides in the generated assembly. Mock is essentially an instance of dynamically generated type implementing your custom interface that comes from dynamically generated assembly:
Mock = dynamic type from dynamic assembly implementing your interface with some smart tracking/setup mechanisms addition
The dynamic type generating library used by Moq, FakeItEasy and RhinoMocks is called Castle Dynamic Proxy. This might sound familiar for Rhino users, as in order to make internals visible to Rhino you actually had to make them visible to DynamicProxyGenAssembly2. This is the assembly Rhino stores castle's proxy types (as briefly explained here).
Where is my private mocking?
Some bells should be ringing by now. If mock is simply derived class, how could it possibly access private method from base class let alone intercept/override it? It can't and that's where the story ends. Note that such problems are non-existing when dealing with interfaces simply because interfaces cannot declare any private members1. The problem also expands on more concepts related to inheritance. Can you override static method? No. There you go, no mocking. What about extension method? Again, same story. Extension method is a static method with some extra treatment from compiler2.
There's one more thing related to mocking classes - class member cannot be mocked unless it's marked with virtual keyword. This should be obvious by now, as in order to track mocked member, mocking frameworks need to derive from class in question and "insert" their own tools instead of member's original body.
At this point we should know which parts of class cannot be mocked. Mocking interfaces is trivial and causes no problems. For classes, general rule is simple:
Cannot override = cannot mock
This essentially leaves out:
- any non-
virtualmember (regardless of access modifier)
- extension methods (this is special case of static method)
- any member of
- fields (but it's kind of pointless to do so anyways)
- RhinoMocks also can't mock
protected virtualmembers; Moq and FakeItEasy allow this using string to access method by name
Is this the definite end? What should we do when we just have to mock (or test) one of those things? I'll address those questions in my next blog post.