In unit testing, all mocks are evil! Now there’s a controversial statement to start a blog post with, but let me explain. I am writing this from my own experience as a software developer and a leader of software developers. This is the sort of thing that software religious wars are made of, so if you agree, or disagree, I would love for you to share your thoughts in the comments.
I think Mocking libraries, although very powerful, can enable developers to over complicate their unit tests. Unit tests should be short and easy to understand. I have lost count of the times where I have seen a developer mock out more than they need to because of excessive class coupling in their code. Just because you can mock out any object doesn’t mean that you should and avoid reducing excessive coupling.
I have also seen mocks being used by developers that abuse the layering and design of their solution. As an example, we have a 3rd part consultancy company writing some code for us to help augment our team numbers. Just recently myself and another group of leads were reviewing this consultancies code. They were developing a web service and on the face of it, were composing their code in layers. They had a service layer, calling a business logic layer, calling a data access layer. All sounding very familiar and normal at this point.
What we then found was they had huge amounts of business logic that had been put into the data access layer and not in the business logic layer. This raised quite a few alarm bells, so we looked at the tests. What we found was not nice. They had written a series of tests for the business logic layer that completely mocked out the data access layer. Normally this is fine as you don’t want to actually hit a database in a unit test, but what they had done was actually mock out the majority of their business logic which meant the tests were not doing anything useful at all.
Whilst I am picking on this one example, this is not the only case where I have seen mocking libraries used for evil.
So, what do I prefer instead. My own preference, and this is one I practice with my own team, is to write code to interfaces and use simple dependency injection to inject implementations into your code. By doing this instead I feel you have much more control over your code and your tests generally end up easier to write once you get used to this way of coding. I have written another post on simple dependency injection, so I recommend reading that.
In my team I have pretty much outlawed the use of mocking libraries on new or previously refactored and cleaned code, there just is no need to use them as we practice writing well designed code written to interfaces and following the SOLID principles.
SOLID is a set of design principles that every software developer who practices object oriented design should follow. If you follow these principles then you will find that you really don’t need to use mocking libraries (on new code at least, more on that later). The SOLID principles are:
S – Single responsibility principle. An object should have only a single responsibility.
O – Open/Closed principle. Objects should be open for extension, but closed for modification.
L – Liskov substitution principle. Objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program. This is also known as design by contract.
I – Interface segregationpPrinciple. Many client specific interfaces are better than one general purpose interface.
D – Dependency inversion principle. One should depend on abstractions. Do not depend upon their concretions. This is where you decouple comes into play.
A very good book that covers the SOLID principles is Clean Code, by Robert C. Martin. I recommend that every software developer should read this book.
As I stated above, if you rigorously follow these principles and ingrain them into the way you right code, you will find that you genuinely do not need to resort to mocking libraries to mock out dependencies as your code will naturally start to become decoupled. I would even go as far as saying that if you feel the need to use a mocking library then that should be a code smell indicating there is a design problem.
Mocking libraries do have their place though. As with most tools, they are a valuable tool in your tool box for specific purposes. If you inherit a large, badly written legacy system, otherwise known as a Big Ball of Mud, the first thing you want to do before changing the code is get some tests around what is there already. These tests are called characteristics tests. This is where you need to test what the current functionality does. This functionality may be wrong or buggy, but you want to get a test suite in place so that you know whether you have broken/changed anything as part of your refactoring. Normally because of excessive class coupling you will need to use a mocking library to write these tests. In this scenario I think mocking libraries are perfect and this is when I would use them, but as you start refactoring your code and trying to introduce some of the solid principles you need to plan for how you are going to remove these mocks and write simpler tests.
There is a great book on all of this called Brownfield Application Development in .NET by Donald Belcham that covers this exact subject.
That concludes my views on mocking frameworks. I am sure there are developers reading this thinking “Hey, I use mocks and can write decent tests that work at the correct layers”, and I am sure you can. Part of my view on this subject comes from leading mixed ability teams of developers where I have seen these libraries abused so many times before. I now encourage my team to work with the SOLID principles and write tests the good old fashioned way.
I know this is a subject that developers are passionate about. I am not claiming this way is the only way, but it is the way that works for me and my team. If you have any views on this, then I invite you to share them in the comments for this post.