What should we do to start mocking?

In the most simple case, we extract the interface from the functionality we want to mock and prepare another implementation that returns mock results. Unfortunately, there are few problems: first, this code may be the legacy one (so there’s no chance for any change in code) and second, preparing full mock implementation may take a lot of time (that doesn’t make much sense, if you just need 1 method mocked - but it’s a different method in each unit test). Of course we have to provide the way to call our implementation instead of original one - that usually means that original code and unit test code will have a different “executing layer” (what means that our test code doesn’t really test what should be tested…). Introducing IoC container won’t solve it really.

The other approach is to use specialized mocking library. Majority of them are quite simple - they require extracted interface and they heavily use reflection. That unfortunately means they may be no use for legacy code. Isolator is quite different - it uses profiler API in execution time (like Microsoft Moles), so there’s no need for extracting interface. You can mock any code, including .NET framework assemblies classes.

How do we mock anything?

Let’s assume we’d like to fake some behaviors or class named “SuperComplexStuff”. First, we’d like to get an instance of that class:
SuperComplexStuff stuff = Isolate.Fake.Instance<SuperComplexStuff>();
Our code may now refer to “stuff” just like to any other SuperComplexStuff instance, but that doesn’t look much useful for now - we won’t use this particular object instance by putting it directly in functional code, will we? Instead of that, we can fake every future instance of SuperComplexStuff:
Isolate.Swap.AllInstances<SuperComplexStuff>.With(stuff);
That makes much more sense - if we mock factory class with such code sample, every create instance of factory will be the mocked one! That looks very useful. If you don’t need all the future instances swapped or you want to swap next instances with different fakes, you can swap just the next created instance using following code:
Isolate.Swap.NextInstance<SuperComplexStuff>.With(stuff);
So, we have a fake object, but how could we fake its behavior? It’s really easy - we just “attach” / “substitute” method / property behavior with something we provide. Like that:
Isolate.WhenCalled(() => stuff.VeryTrickyMethod1()).CallOriginal();
Isolate.WhenCalled(() => stuff.VeryTrickyMethod1()).IgnoreCall();
Isolate.WhenCalled(() => stuff.VeryTrickyMethod2()).WillReturn(new FakeResult());
Isolate.WhenCalled(() => stuff.VeryTrickyMethod3()).WillThrow(new NastyException());
Isolate.WhenCalled(() => stuff.VeryTrickyMethod4()).DoInstead(callContext => …);
These are just few basic examples. Fluent syntax is very clear, so I will skip detailed descriptions that don’t seem necessary here. Preceding examples are just the Isolator fundamentals - you can do much more:
  • mock every method call or just calls with specific parameters
  • mock every method with parameters meeting custom criteria
  • mock properties in the same way you can mock methods
  • assert code call conditions (if something was or was not called, regardless of parameter values or for given parameter values)
  • do pretty much all the same stuff from above with private methods / properties (API is different as they are not available directly for obvious reasons)
  • swap all calls to fake with calls to some other instance
  • decide on the way fake object is constructed (if original constructor should be called or not)

To Be Continued …

Share this post