Make it simpler : get rid of Mocking Fx
By Jérémie Chassaing on Thursday, June 14, 2012, 14:32 - Design - Permalink
In the wake of Rinat Technology Demons, I’d add Mocking frameworks to the list.
There are several reasons to do that.
Stubs
One of the usage of Mocking - or isolation – frameworks is stubbing. A component that access external resources or has complex behavior will be changed for a fake to have simpler predictable results.
- When the component interface is small, the stub declaration code is often more complicated that writing a fake implementation directly.
- When the interface has many methods, it makes things easier, but here you’ll ignore a code smell. It makes things easy in situation you should not reach !
There are also easy patterns that make the use of mocking irrelevant. A common one is configuration loading.
Lots of developers think: “I need a class to access my configuration. Let’s make a class for this”:
public class Configuration
{
public string EndPoint
{
get { return ConfigurationManager.AppSettings["EndPoint"]; }
}
// other properties here//
}
Then they realize they’ll have to isolate from ConfigurationManager, so they add a interface :
public interface IConfiguration
{
string EndPoint { get; }
}
public class Configuration : IConfiguration
{
public string EndPoint
{
get { return ConfigurationManager.AppSettings["EndPoint"]; }
}
// other properties here//
}
And they can moke the configuration using a lot of boring code.
what about this ?
public class Configuration
{
public string EndPoint { get; set; }
// other properties here//
}
public class ConfigurationLoader
{
public Configuration Load()
{
return new Configuration
{
EndPoint = ConfigurationManager.AppSettings["EndPoint"]
// other properties here//
};
}
}
Passing a different configuration in your test is a simple new Configuration {}… and you can use the ConfigurationLoader class in you main function.
A good thing here, is that you don’t suffer a read of the configuration file at each call without needing to introduce lazy loading or other tweaks that make things worse..
Mocks
When you need to see if a call happened, you can make an implementation of the interface that takes a lambda :
public interface IFancyService
{
void DoSomething(int arg);
}
public class MockFancyService : IFancyService
{
private Action<int> doSomething;
public MockFancyService(Action<int> doSomething)
{
this.doSomething = doSomething;
}
public void DoSomething(int arg)
{
doSomething(arg);
}
}
public class Test
{
void DoSomthingHasBenCalled()
{
bool wasCalled = false;
var fancyService = new MockFancyService(i => { wasCalled = true; });
var compoenent = new ComponentThatUseFancyService(fancyService);
compoenent.MakeSomething();
Assert.That(wasCalled, Is.True);
}
}
Or make the fake class record the call, and add a getter to check. It’s not that complicated.
Comments
In your first example, how do you prevent developers from using Configuration, instead of ConfigurationLoader, directly, especially given that it would seem the more obvious choice if nobody was instructing you which to use?
In the second example, it seems to me that having to write MockFancyService requires a lot more code than just using Moq (or similar) and adding one line to my test with my expectation that s => DoSomething() happened. Nevermind if I need DoSomething to return a value for my method to work correctly, and a different value in another test, etc.
I'm not saying you shouldn't look to simplify where you can, and definitely I agree that fat interfaces are a smell to be avoided. But I think the do-it-all-yourself approach results in a lot of DRY violation and reinvention of wheels already included as features of any mocking framework.
There's nothing to prevent the developers. But since the Configuration class is just a DTO, it does nothing, you have to load config from somewhere. The ConfigurationLoader is here for that, and since it's simply a function, you can even make it static. No prb for me.
In the second example, there are a lot of ways to make it simple without using a framework. C# is good at that. Usually, a few line of code will suffice depending on what you'll need to test. You could still use a mocking fx there if you prefer. But there are also other ways to get rid of mocking by using things like Event DTOs (see Simple.Testing...).
Configuration: feels like if my class needs access to Configuration, then it's caller, and it's caller's caller, and it's caller's caller's caller, etc... will need to pass this DTO down through the call stack from the service layer.