Using Mocking Framework - Moq

kick it on DotNetKicks.com
StumbleUpon.com
Save to delicious Saved by 0 users



This post will tell how to incorporate one of the popular & free object mocking framework, Moq in your unit tests.


I am sure you have heard about this if you have done unit tests before or you have experience in software development project that employs the TDD (Test Driven Development) approach.

What actually is a mock object? An object that mimics the behavior of real object in a controlled way. Mock objects are often used in unit test to simulate the behaviors of the dependencies for the object being tested. Mock objects are used because in real life the real objects are very impractical or impossible to create in the unit test environment. It is impractical and impossible because configuring and setting up all these real dependencies subjected to budgets, time or unavailability of the real dependencies at the time the unit testing is performed. For e.g. to unit test an object that uses a database, you  can easily setup up a SQL Server database connection with the Visual Studio and it is fairly simple and manageable task. What if the objects you need to test also depend on other data source that resides on the mainframe server in a secure environment or other third-party library that is still under development?

Let assume all the constraints to set up and configure the real dependencies for the objects to be tested don’t exist, then the unit tests themselves will look like the integration tests. This will defeat the purpose of unit testing as the unit test is to isolate each part of the program and to ensure each of this individual parts meet its design and behaves as intended. It meant to be simplest, fast and exercise very specific functionality.

The setting up and configuration of the real dependencies for the objects being tested should be deferred until the integration testing where the idea is to test the combination of units and to identify problems that occur when units are combined. It will eventually expand to testing the modules with those of other groups and finally all the modules that make up the process are tested together. It is significant slower than the unit testing.

The mock objects replace the real dependency objects and the objects that depend on them can be tested easily and effectively without being aware of the fact they are being served by the mock objects. This is possible because the mock objects conform to the interface of the real objects and they just have enough code to fool the tested objects.  With mock objects, developers can focus on testing the behaviors of the system under test without worrying on the complex dependencies which are awkward to create in the unit test environment. Click here to know more about the history of mock objects.

There are other thoughts from Gerard Meszaros and Martin Fowler that a more generic term, Test Double, should be used instead of the mock for any case where replace real objects for testing purposes. Under the test double term, there are few names to describe the specific implementations. The table below is taken from http://msdn.microsoft.com/en-us/magazine/cc163358.aspx

Test Double TypeDescription
DummyThe simplest, most primitive type of test double. Dummies contain no implementation and are mostly used when required as parameter values, but not otherwise utilized. Nulls can be considered dummies, but real dummies are derivations of interfaces or base classes without any implementation at all.
StubA step up from dummies, stubs is minimal implementations of interfaces or base classes. Methods returning void will typically contain no implementation at all, while methods returning values will typically return hard-coded values.
SpyA test spy is similar to a stub, but besides giving clients an instance on which to invoke members, a spy will also record which members were invoked so that unit tests can verify that members were invoked as expected.
FakeA fake contains more complex implementations, typically handling interactions between different members of the type it's inheriting. While not a complete production implementation, a fake may resemble a production implementation, albeit with some shortcuts.
MockA mock is dynamically created by a mock library (the others are typically produced by a test developer using code). The test developer never sees the actual code implementing the interface or base class, but can configure the mock to provide return values, expect particular members to be invoked, and so on. Depending on its configuration, a mock can behave like a dummy, a stub, or a spy.

While the unit testing has gained popularity in recent years, so do the number of mocking frameworks available for .NET. The mocking framework helps to simplifying the way the mock implementations of dependencies of the object under test are created. Some are open source like NUnit.Mocks, NMock, NMock2, EasyMock, Rhino.Mocks, Moq and some are commercial such as TypeMock . Here are two links that compare few of them http://www.phpvs.net/2009/04/25/net-mocking-frameworks-capability-comparison/ and http://codevanced.net/post/Mocking-frameworks-comparison.aspx .

Frankly speaking, I first experienced with unit testings only two and a half years ago. At that time, I was attached with one the US software company that provides customer relationship management solutions. The company practices agile software development. So, unit testing is one of the practices. The first unit testing framework I used is NUnit. However, in real work practices, the real dependencies are often handcrafted from scratch without relying on the use of mocking frameworks. Well, I am not really a full fledged TDD developer but I will try to commit myself to it as often as possible and this would also depend on whether the organization has the culture of practicing TDD.  Sometimes, the tight delivery time may have caused the unit testings being singled out for the sake of meeting the deadlines.

The mocking framework is new to me. In this post, I have chosen to use the open source Moq (pronounced “Mock-you” or just “Mock”) instead of the more popular open source Rhino.Mocks because of its simplicity in term of its API. Unlike other mocking frameworks, Moq doesn't use the record/replay model explicitly. So, its APIs are more intuitive to use and easy to learn. To learn what the record/replay mean in the TDD, please click What's wrong with the Record/Reply/Verify model for mocking frameworks, to follow the explanation by the Moq creator. Also, there is no real distinctions among the Test Double types in Moq. All of them are referred to as Mock. For a new comer like me, it poses less confusion as I can simply create whatever Test Double object through a single API, Mock.  Accessing any of its mocking utilities is just simply a dot away from the Mock instance.

The use of Moq is my personal preferences. I don't deny the pros of other mocking frameworks as each of them has its merits and users around the world. It is only that I find Moq is easy to start with and it is easy to pick up fast. Anyway, there is no harm to learn Dummy vs Stub vs Spy vs Fake vs Mock as you move along and get comfortable with the mocking. There is a link,  Mocks Aren't Stubs by Martin Fowler that explain this in further details.

Again, based on the Moq creator, it is intended to be straightforward and easy to use mocking framework that doesn’t require any prior knowledge of the mocking concepts. So, it doesn't requires deep learning curve from the developers.  It takes full advantage of the .NET 3.5 expression trees and the lambda expressions. Any of the methods and properties of the mock object can be easily represented in the lambda expressions.
Moq can be downloaded from the below link and it is maintained as the Google Code project.
http://code.google.com/p/moq/

In the rest of the post that follows, I will write the unit tests for the repository with mocking features available from the Moq. The repository APIs are what I have introduced in my writing on Repository, Specification, Unit of Work and Persistence Ignorance with Microsoft Entity Framework 4.0 Beta 2. You can read the post here. Your comments and feedback are always welcomed. If you go through the unit test source codes for the repository in the post, you will notice that the unit tests don't make use of the mock objects. Instead, it makes use of all the real dependencies for the testing. I have written all the codes and all those real dependencies such as the MS-SQL server connection, database instance,  entity framework features can be easily managed and  set up within the Visual Studio environment. So,  I have put the use of mocking objects aside. However, in the team environment where each of the team member has its own roles and responsibilities in different area/layer of the software development and because of the separation of concerns, it is very hard or impossible to have all the real dependencies ready to be used at the time when you want to carry out the unit testing on the codes you have written. In this situation, mocking objects will come into the picture and you will find that they are very helpful and make your life easy. Furthermore, unit testing with the real dependencies will sometimes make your tests fail unexpectedly because of the changes of configuration settings or errors in the real dependencies which are beyond your control.

Make sure you have downloaded the latest stable version of Moq which is Moq.3.1.416.3-bin.zip as of this writing.

Some basics of the Moq
i) It can mock both interfaces and classes, and use lambda expressions to make those mocks type safe and refactoring friendly.
ii) However, it cannot mock non-virtual, non-abstract and static methods, and can't mock sealed classes and private interfaces.

Without further ado, let look at the example:
I will unit test the Customer repository class again in the business layer project. But, this time I am going to take out the real dependencies in the CustomerRepository class and replace with mock objects. Figure 1.o shows the CustomerRepository that I am going to unit test against the Moq framework.  In my previous post on using Repository, Specification, Unit of Work and Persistence Ignorance POCO with Microsoft  Entity Framework 4.0 Beta 2, I have unit tested the business layer, CustomerRepository with all the real dependencies.


 Figure 1.0 CustomerRepository in the business layer project, MyCompany.Business.MoqDemo

At the first glance of my CustomerRepository type, it has direct dependencies on MyCompany.Data.RepositoryFactory and MyCompany.Data.Repository/IRepository interface. So, these two types are candidates for the mock objects. However, when I carefully look at the RepositoryFactory, which is a singleton class and can't be mocked directly with Moq framework without using some workaround like applying the Adapter pattern to the RepositoryFactory. Well, if you see it from the design by testability perspective; static methods, singleton and concrete types are not encouraged and they  limit the testability of  a type if they are not properly used.  Follow this link to read opinions of other people why singleton is bad. There are two articles from msdn magazine; Tame Your Software Dependencies for More Flexible Apps and Design for Testability, which I found very useful in telling how to write flexible application with loosely coupled and testable types.

Now, I admit that implementing the RepositoryFactory as singleton would be a wrong design decision if I want it to be easily mocked with Moq. Assuming that this is a fact and I can't change the RepositoryFactory code implementation but to live with it. My workaround solution to make RepositoryFactory mockable is to write a RepositoryFactory wrapper for it.

1:  public class RepositoryFactoryWrapper : IRepositoryFactory where TObject : class  
2:    {  
3:        private RepositoryFactory _repositoryFactory;  
4:        public RepositoryFactoryWrapper(RepositoryFactory repositoryFactory)  
5:        {  
6:          _repositoryFactory = repositoryFactory;  
7:        }  
8:       #region IRepositoryFactory<TObject> Members  
9:        public TObject CreateObject()  
10:       {  
11:          return _repositoryFactory.CreateObject();  
12:       }  
13:       public TObject CreateObject(string name)  
14:       {  
15:        return _repositoryFactory.CreateObject<TObject>(name);  
16:       }  
17:       #endregion  
18:    }  

Based on the above code segment, the RepositoryFactoryWrapper merely delegates method calls to the original MyCompany.Data.RepositoryFactory.


1:   public class CustomerRepository  
2:    {  
3:      private readonly IRepositoryFactory<IRepository<Customer>> _customerRepositoryFactory;  
4:      //Explict public default constructor  
5:      public CustomerRepository()  
6:      {  
7:        _customerRepositoryFactory = new RepositoryFactoryWrapper<IRepository<Customer>>(RepositoryFactory.Instance);  
8:      }  
9:      public CustomerRepository(IRepositoryFactory<IRepository<Customer>> repositoryFactory)  
10:     {  
11:        _customerRepositoryFactory = repositoryFactory;  
12:     }  

Based on the above code segment, my CustomerRepository will have two constructors. The first one is the default constructor which the client component will call by default when the CustomerRepository is created. Within the default constructor, an instance of the RepositoryFactory will be returned from its singleton pattern and passed as parameter to the RepositoryFactoryWrapper's constructor.The second constructor of the CustomerRepository is for us to pass our mock object of the IRepositoryFactory interface during the unit testing.

Now we have all the infrastructure in place, we can use Moq to achieve our mocking purposes. The general steps to work with the mocking frameworks are as follow:-

1. Create a mock object from an exiting interface or classes with the mocking framework. In Moq, it can be easily achieved with Mock .
2. Set the expectations for the mock object. This is to tell the mocking framework what will be called, returned, set, get and etc on the mock object.
3. Pass the mock object to the object that depends on it during the unit testing.
4. Verify the expectations were met.

Let look at the CustomerRepositoryTest as an example.


1:    /// <summary>  
2:    /// Unit tests for customer repository.  
3:    /// </summary>  
4:    [TestClass]  
5:    public class CustomerRepositoryTest  
6:    {  
7:       private Mock<IRepositoryFactory<IRepository<Customer>>> _customerRepositoryFactoryMock;  
8:       private Mock<IRepository<Customer>> _customerRepositoryMock;  
9:       private List<Customer> _customerList;  
10:      private CustomerRepository _customerRepository;  
11:      public CustomerRepositoryTest()  
12:      {  
13:        //setup our mock objects here.  
14:        _customerRepositoryFactoryMock = new Mock<IRepositoryFactory<IRepository<Customer>>>(MockBehavior.Strict);  
15:        _customerRepositoryMock = new Mock<IRepository<Customer>>(MockBehavior.Strict);  
16:        //Collection Initializer  
17:        //Simulate the persistent in memory storage for the Customer Repository Tests  
18:        _customerList = new List<Customer>() { new Customer{ CustomerID = "TEST1", ContactName = "TestCompanyName1"},  
19:                            new Customer{ CustomerID = "TEST2", ContactName = "TestCompanyName2"},  
20:                            new Customer{ CustomerID = "TEST3", ContactName = "TestCompanyName3"}};  

In the constructor of CustomerRepositoryTest, we setup our mock objects for IRepositoryFactory> and IRepository using the Mock class. It has a generic type parameter which accepts the type of the interface of  the mock object to create. You will notice that the Mock constructor accept the MockBehavior enum option which can take three values; Strict, Loose and Default. I have chosen to use the Strict option. So during the unit testing if there is any method call made on these two dependencies in the CustomerRepository instance doesn't have the corresponding expectation being setup, then the Moq framework will throw an exception telling me that the invocations don't have a corresponding setup. The Loose option will mean that the Moq framework won't throw any exception but will try to create default value as necessary.

For e.g. In the implementation of the public methods API of the CustomerRepository, there is call to the IRepositoryFactory>.CreateObject() to return an instance of the generic customer repository. If I didn't setup the expectation for the IRepositoryFactory>.CreateObject() method, the Moq will throw an exception when encountering a call to the CreateObject() method in the CustomerRepository class. If the Loose option is used, then the Moq will ensure CreateObject() method returns a null reference instead of throwing and exception. The Default option is actually Loose option.

After the mock objects are setup, we will move to the expectations setup for the mock objects. Prior to this, I have created a list of customer collection for the purpose of CRUD operations performed on the IRepository mock object. It serves as an in memory storage for holding up all the customer entity objects.

1:   //Setup expectation for the Dispose method of the IRepository<Customer> mock  
2:   _customerRepositoryMock.Setup(cr => cr.Dispose());  
3:   //Setup expectation for the Create method of the IRepository<Customer> mock  
4:   _customerRepositoryMock.Setup(cr => cr.Create()).Returns(new Customer());  
5:   //Setup expectation for the Add method of the IRepository<Customer> mock  
6:   _customerRepositoryMock.Setup(cr => cr.Add(It.Is<Customer>(c => !string.IsNullOrEmpty(c.CustomerID)))).Callback((Customer c) =>  
7:   {  
8:    _customerList.Add(c);  
9:   }  
10:   );  
11:  //Setup expectation for the Attach method of the IRepository<Customer> mock.  
12:  _customerRepositoryMock.Setup(cr => cr.Attach(It.Is<Customer>(c => !string.IsNullOrEmpty(c.CustomerID))));  
13:  //Setup expectation for the Update method of the IRepository<Customer> mock.  
14:  _customerRepositoryMock.Setup(cr => cr.Update(It.Is<Customer>(c => !string.IsNullOrEmpty(c.CustomerID) && _customerList.Exists( d => d.CustomerID == c.CustomerID)))).Callback  
15:  ((Customer c) =>  
16:  {  
17:    //update the customer object in the memory customer list storage  
18:    Customer tempCustomer = _customerList.SingleOrDefault(e => e.CustomerID == c.CustomerID);  
19:    tempCustomer.Address = c.Address;  
20:    tempCustomer.City = c.City;  
21:    tempCustomer.CompanyName = c.CompanyName;  
22:    tempCustomer.ContactName = c.ContactName;  
23:    tempCustomer.ContactTitle = c.ContactTitle;  
24:    tempCustomer.Country = c.Country;  
25:    tempCustomer.Fax = c.Fax;  
26:    tempCustomer.Phone = c.Phone;  
27:    tempCustomer.PostalCode = c.PostalCode;  
28:    tempCustomer.Region= c.Region;  
29:   }  
30:  );  
31:  //Setup expectation for the delete method of te IRepository mock.  
32:  _customerRepositoryMock.Setup(cr => cr.Delete(It.Is<Customer>(c => !string.IsNullOrEmpty(c.CustomerID) && _customerList.Exists(d => d.CustomerID == c.CustomerID)))).Callback  
33:  ((Customer c) =>  
34:   {  
35:    //remove the customer object from the memory customer list storage  
36:    int index = _customerList.FindIndex(d => d.CustomerID == c.CustomerID);  
37:    if (index > -1)  
38:    _customerList.RemoveAt(index);  
39:   }  
40:   );  
41:   //Setup expectation for the Save method of the IRepository<Customer> mock.  
42:   _customerRepositoryMock.Setup(cr => cr.Save()).Returns(1);  
43:   //Setup expectation for the customer repository factory to return the IRepository<Customer> object  
44:   //from the IRepository<Customer> mock.  
45:   _customerRepositoryFactoryMock.Setup(c => c.CreateObject()).Returns(_customerRepositoryMock.Object);  
46:   //Pass the IRepositoryFactory<IRepository<Customer>> object the specific customer repository object which the unit test will test against.  
47:   _customerRepository = new CustomerRepository(_customerRepositoryFactoryMock.Object);  

The above code segment shows all the expectations being setup on the two mock objects having the interface IRepositoryFactory and IRepository.
The expectations on the mocked type can be specified with the Setup() method. In version 2.x, it is named as Expect. The Setup() method let us specify the methods we expect the mocked type to be called during the unit testing along with its parameter as well as the return value if there is any. The statement  _customerRepositoryMock.Setup(cr => cr.Dispose()) tell the Moq framework that the Dispose() method on the interface IRepository will be called during the unit testing. So, the Moq framework will be able to provide a mocked implementation of this Dispose() method for the interface IRepository.

Let look at this statement,  _customerRepositoryMock.Setup(cr => cr.Create()).Returns(new Customer()) . The method expectation requires a return value as part of its invocation. When the Create() method is invoked, a new Customer entity object will be returned.
Let look at this statement,

_customerRepositoryMock.Setup(cr => cr.Add(It.Is(c => !string.IsNullOrEmpty(c.CustomerID)))).Callback((Customer c) =>
{
     _customerList.Add(c);
}

);

The static class, It allows us to pass constraint to the method expectation. The It.Is will match any values that satisfy a predicate. The above statement tell the Moq framework that the Add() method only accept a customer entity object whose CustomerID property is not null or empty. If this constraint is not being obeyed during the method invocation, then Moq framework will throw an exception  if  Strict enum is specified for the MockBehavior.

The Callback allow us to specify or includes a chunk of codes to be executed during the method invocation. It similar to the body of the method. When the Add() method is invoked, the customer entity object argument is passed to the callback body which merely add the customer entity object to the in memory customer list,  _customerList.

So far, you will notice that all the method expectations are represented in lambda expressions which make the mock type safe and refactoring friendly. One more thing to notice is that last two statements of the code segment.

1:  //Setup expectation for the customer repository factory to return the IRepository<Customer> object  
2:  //from the IRepository<Customer> mock.  
3:   _customerRepositoryFactoryMock.Setup(c => c.CreateObject()).Returns(_customerRepositoryMock.Object</span>);  
4:  //Pass the IRepositoryFactory<IRepository<Customer>> object the specific customer repository object which the unit test will test against.  
5:  _customerRepository = new CustomerRepository(_customerRepositoryFactoryMock.Object);  


The Object property return the instance of the mocked objects of both interfaces IRepositoryFactory> and IRepository respectively. _customerRepositoryMock is not returned as part of the method expectation, CreateObject() method because it is merely a proxy class that hold the actual mocked instance.
Last but not least, there is a limitation of the Moq mocking framework. Please look at the following code segment. I expect the following would be possible

1:  _customerRepositoryMock.Setup(cr => cr.Find( c => c.CustomerID == "TEST4")).Returns(() => _customerList.Where(c => c.CustomerID == "TEST4").AsQueryable());  

However, I get a NotSupportedException error during the run time as shown in Figure 1.1


 Figure 1.1 NotSupportedException error when passing lambda expression to the method that can accept expression input.

This post just introduces the basic usage of the Moq framework APIs. If you are into it, you can refer to the Moq quick start here which shows a more complete sample of how its APIs can be harnessed.

Code Download Customer Repository Unit Test with Moq object framework. (This application sample requires Visual Studio 2010 Beta 2/RC that can open C# project. Right click on the above link and choose Save Target As. Rename the extension from .pdf to .zip once you have downloaded the file. Let me know if you have any problem running the code.)

See you in my next post.
Bye and stay tune...


0 comments:

Post a Comment