Unit testing the DAL has always resulted in a debate: whether to mock or not the Data Access Layer.
Indeed, there are cases were the DAL cannot be legally tested without hitting the real production database (requires integration testing). The goal behind that is to assure us of the behavior of some database server specific features like primary key generation, handling schema alternations with pre-populated data, triggers, etc..
However for testing the Business Logic Layer , the validation logic or the presentation layer, it is fair to say that accessing the database is not obligatory. In this post I will discuss a sample mocking framework for mocking the DAL based on the Telerik OpenAccess ORM. The main entry point for working with OpenAccess is the IObjectScope. So, it is reasonable that this is the first thing that requires mocking. Instead of developing a mocked version of the IObjectScope, I wrote this far simpler interface called IMockedObjecScope. The reason for that is that the IObjectScope contains lots of methods that simply cannot get a real mocking implementation or there is not a reasonable need for one like GetOqlQuery, GetSqlQuery, IsTransient, Refresh, etc.

So here is the IMockedObjectScope interface:

public interface IMockedObjectScope
{
    
void Add(object newObject);

    
void Remove(object objectToBeRemoved);

    
IMockedTransaction Transaction { get; }
}

It contains the two essential methods for our Insert and Delete operations – the Add and Remove as well as another very important member, the IMockedTransaction which is a mocked version of the OpenAccess Transaction.

Here is how this interface looks:

public interface IMockedTransaction
{
  
void Begin();
  
void Commit();
  
void Rollback();
  
bool IsActive { get; }
}

The implementations of these two interfaces are based on the repository pattern that wraps in-memory representation of the database using dictionaries and lists  of persistent objects. The following is the implementation of the MockedObjectScope class:

    public class MockedObjectScope:IMockedObjectScope
   
{
       
private IMockedTransaction transaction;

       
#region IMockedObjectScope Members

       
public void Add(object newObject)
       
{
           
if (transaction.IsActive)
           
{
               
PersistentClassRepository.AddToTemporaryListForInsert(newObject);
           
}
           
else
           
{
               
throw new Exception("There is no active transaction");
           
}
       
}

       
public void Remove(object objectToBeRemoved)
       
{
           
if (transaction.IsActive)
           
{
               
PersistentClassRepository.AddToTemporaryListForRemove(objectToBeRemoved);
           
}
           
else
           
{
               
throw new Exception("There is no active transaction");
           
}
       
}       

       
public IMockedTransaction Transaction
       
{
           
get { return transaction; }
       
}

       
#endregion

       
public MockedObjectScope()
       
{
           
transaction = new MockedTransaction();
       
}
   
}


    public static class ExtensionMethod
   
{
       
public static IQueryable<T> Extent<T>(this IMockedObjectScope scope)
       
{
           
return (IQueryable<T>)PersistentClassRepository.PersistentObjects[typeof(T)].AsQueryable();
       
}
   
}

The Extent extension method is also added to the MockedObjectScope so I can execute my load of data operations using Linq in the same manner as I would be doing so with the real IObjectScope. The Add and Remove methods always check for an active Transaction as is in the real IObjectScope implementation and if the condition is met the objects are added to temporary lists for the corresponding operation. These temporary lists are then inserted in the “in-memory database” on Transaction.Commit() or cleared on Transaction.Rollback().

This is the logic implemented in the mocked version of the Transaction:

    public class MockedTransaction:IMockedTransaction
   
{
       
private bool isActive;

       
#region IMockedTransaction Members

       
public void Begin()
       
{
           
if (IsActive == true)
           
{
               
throw new Exception("Nested Transactions are not allowed");
           
}
           
else
           
{
               
this.isActive = true;
           
}
       
}

       
public void Commit()
       
{
           
if(PersistentClassRepository.TempListForInsert.Count>0)
           
{
               
foreach (var persistentObject in PersistentClassRepository.TempListForInsert)
               
{
                   
PersistentClassRepository.Add(persistentObject);
               
}
           
}
           
if (PersistentClassRepository.TempListForRemove.Count > 0)
           
{
               
foreach (var persistentObject in PersistentClassRepository.TempListForRemove)
               
{
                   
PersistentClassRepository.Remove(persistentObject);
               
}
           
}
           
isActive = false;
       
}

       
public void Rollback()
       
{
           
PersistentClassRepository.TempListForInsert.Clear();
           
PersistentClassRepository.TempListForRemove.Clear();
           
isActive = false;
       
}

       
public bool IsActive
       
{
           
get
           
{
               
return this.isActive;
           
}
       
}

       
#endregion
   
}

The PersistentClassRepository which is the final part of my mocking implementation is a generic, model-independent class that can be reused for all kinds of scenarios. It contains the logic for inserting and removing persistent instances as well as persisting object graphs so there is not a great difference with the IObjectScope behavior. Here are the members of the PersistenClassRepository:

private static Dictionary<Type, IList> persistentObjects = new Dictionary<Type, IList>();
private static List<PersistenceCapable> tempListForInsert = new List<PersistenceCapable>();
private static List<PersistenceCapable> tempListForRemove = new List<PersistenceCapable>();

In order to save a little space on this blog I will leave the implementation of the PersistentClassRepository static methods for you to see in the Telerik OpenAccess code library.
So, finally I have a mocked implementation to unit test my OpenAccess-related logic without connecting to a database at all!  Here is a sample MSTest method that uses the mocking infrastructure:

[TestMethod]
public void InsertValidProduct_WithInvalidCategory_ShouldNotEnterInTheRepository()
{
   
Product prod = new Product();
   
prod.ProductID = 5;
   
prod.ProductName = "TestProduct";
   
Category cat = new Category();
   
int catId;
   
int.TryParse("999999999999",out catId);
   
cat.CategoryID = catId;
   
cat.CategoryName = "TestCategory";
   
prod.Category = cat;
   
mockedScope.Transaction.Begin();
   
if (Validation.ValidateProduct(prod) && Validation.ValidateCategory(prod.Category))
   
{
       
mockedScope.Add(prod);
       
mockedScope.Transaction.Commit();
   
}
   
else
   
{
       
mockedScope.Transaction.Rollback();
   
}

   
IQueryable<Product> productQuery = mockedScope.Extent<Product>().Where(p => p.ProductID == 5);
   
Assert.AreEqual(0, productQuery.Count());
}

I guess some of you already noticed that our mocking implementation lacks the U - from CRUD. The Update operations are much more specific if we want to really mock them e.g. mocking the OpenAccess change-tracking mechanism. I will leave that for my second blog post on this topic where some new mocking techniques on OpenAccess persistent classes will be introduced.

 

Download the full code.


Comments

Comments are disabled in preview mode.