We have several posts on the Internet that focus on Test Driven Development and its benefits. There is a group of SCRUM Masters around who emphasize on how Test Driven Development (TDD) is beneficial and can change the way you write and test code. I completely agree that Agile and TDD can help you manage your teams, code, product quality and communication in a better way. But this is not yet another post on Test Driven Development, or Unit Testing. This is one of the articles on Test Mocking. How is it different from others? This series assumes that you have no knowledge of mocking and your application is not unit-test ready so it guides you on the concept of mocking, preparing your application, using mocking frameworks, comparing them and ensuring that your code is 'Well-Tested and Covered'
So let's get started!
Understanding Mock – What, Why?
Now if you are following the discipline of TDD and are building large scale enterprise application that interacts with services, databases, or other data sources, writing data driven unit tests becomes a challenge. Test setup (for each test) becomes more complicated and challenging than the actual unit test. This is where the concept of Mock comes into picture.
Mock - to deceive, delude, or disappoint.
As the English definition of the word Mock suggests we want to deceive the process of unit test with a substituted data rather than retrieving a data set from the actual service or database. This also means that we are getting rid of various other aspects of service availability, environment setup, data masking, data manipulation and conversion. It is like telling the unit test
Do not worry about the data source. Stop worrying about the actual data and use the mocked up data. Test the logic!
OK, this sets a premise on why mocking is required! Do you need an alternate definition to understand this even better?
A mocking framework fakes objects to replace any dependencies you have and thereby, allow you to tell them (the mocked code) to behave as you want it to. So even if the service may not exist if you have asked the mocking framework to mock it, the mocking framework will provide a fake service when requested by the consuming code.
Refactoring application to be Unit Test ready
Let’s assume that you were told one fine day that your application, for the simplicity is a typical 3-tier web application, needs to be unit tested. So you start with the first step of analysing the most critical part that constitutes 80% of your business functionality. Now there are two possibilities – either your application has been designed following the SOLID Principles or it is a legacy application built without considering these design principles. The second possibility requires more effort on your side, so let’s assume that your application is not design correctly and you want to Unit Test it with Mocking.
Single Responsibility Principle - Isolate your data sources
First, try isolating the all the data sources into repositories. This means that if your application is reading configuration from XML file, business data from SQL database, real-time feeds from Web Services, and alike then check if the principle of isolation and single-responsibility is applied correctly. This means that your application should not have a class that defines actions responsible for reading data from multiple sources, manipulate it, do some calculations, or store it.
Your application should have one class object per data source (DAL class) that is responsible for retrieving / storing data in that data source. If the need is to do some calculations, manipulations on one or more data sources, then there should be another class object who should have this responsibility.
Interface Segregation Principle – Use interfaces instead of objects
Now that you have your data sources isolated and have single responsibility of interacting with one-and-only-one data source, your next step is to ensure that all the references of this class object (that represents the data source) is not referenced as an object in all the calling objects.
In simple words code like this,
- ConfigurationStore store = new ConfigurationStore();
Needs to be refactored into something like,
- IConfigurationStore store = new XmlConfigurationStore();
Please note the two changes in the above code. One – instead of creating an object of class ConfigurationStore we are now creating an object of an interface IConfigurationStore and have given more meaningful name to the class as XmlConfigurationStore. This is also referred as ISP
Dependency Inversion and Injection - Refactoring the construction of data source
Now that you have isolation between classes representing data sources and have interfaces defining the definition of these classes, the next step is to ensure that there is no hard dependency on the implementation of these classes. In other words, we don’t want to make our consumer class dependent on the implementation of the class (representing data source) instead we want it to be dependent on the definition of this interface.
Higher level module (the consuming classes responsible for any data manipulations, representation, etc) should not depend on low level module (the object of data source/DAL) rather should depend on a layer of abstraction (like an interface)
This is known as DIP – Dependency Inversion Principle. There are three ways to implement DIP – through constructor while constructing the higher level modules, through properties by assigning the lower level module objects to the property, or explicitly through methods. We will not go into the details of implementation and would advise you to go through the MSDN article on Dependency Injection
So we have a cleaner code that can be referred as unit-test-ready code
Unit Test and Mock – How?
Do we need any special infrastructure? Any third-party frameworks required?
To get started with unit testing, all you need is Visual Studio 2010/2012. Yes, that’s enough for basic testing. We build our unit tests using any one of NUnit, xUnit or MSTest and run them using appropriate tools.
But since you are keen at implementing Mocks, you will require a well tested and proven Mocking Framework. Three frameworks that I’ve used are
- Rhino Mocks – This is unarguably the most adopted and extensive mocking framework with lots of features. Some developers find it difficult the adopt considering a wide range of functionalities available. However, post the series of articles of Mocking using this should not be difficult.
- NSubstitute – Implementing mocking is made extremely easy using this framework
- Moq – This is a great framework when you are developing a Silverlight application
So, get ready to download one of the above frameworks to get your infrastructure ready. If you are still confused which one, then
I would recommend staying connected to this post as in the subsequent articles in the series we will see the differences in the implementation of mocking using these 3 frameworks! We will look more into the 'How' aspects of implementing these frameworks!