How to mock private method with...

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 A.Fake<IUserRepository>() or 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.

Let's recap

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-virtual member (regardless of access modifier)
  • static members
  • extension methods (this is special case of static method)
  • any member of sealed class
  • fields (but it's kind of pointless to do so anyways)
  • RhinoMocks also can't mock protected virtual members; 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.


  1. This is actually restricted by CLR: it requires all interface members to be public and C# compiler simply makes them public for you 

  2. Special ExtensionAttribute is applied to a method and persisted in compiled module's metadata 


Comments

Add new comment

Filtered HTML

  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <blockquote> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
CAPTCHA
Solve the challenge for fame and fortune!