Creating a Generic Base Fake Repository Class
In many enterprise level transactional applications, it is common to make use of a either a two or a three tier architecture, with one of the layers a data access layer. It is useful to have the data access layer loosely coupled, preferably via an IoC tool, in order to be able to “swap out” the real components with fake or stub versions.
For unit testing purposes this can be done using a mocking framework such as Rhino Mocks. It can also be useful to include hard-coded fake repository objects, not only for unit testing but also for prototyping either the front end or the service layer of the application, without requiring a real database and data access layer.
The IRepository Interface
In one of the applications I have been working on, my data access layer objects, implement (at a minimum), the following interface:
public interface IRepository<T> where T: class { T Get(int id); IList<T> GetAll(); IList<T> GetBy(string find, string property, bool exactMatch); T Add(T item); T Update(T item); T Save(T item); IList<T> Save(IList<T> items); bool Delete(int id); bool DeleteAll(); }
Creating Fake Repositories
Inspired partly by Gabriel Schenker’s article on the repository pattern, I created a set of fake repository objects to represent a set of hard-coded, fixed data along with dummy “working” operations. I soon realized that it would be beneficial to make use of a base class for my fake repositories, which provides generic implementations of all the required base methods, i.e.:
public class BaseFakeRepository<T> : IRepository<T> where T :class
{
protected Dictionary<int, T> _dictionary;
protected Expression<Func<T, int>> _identityExpression;
public BaseFakeRepository(Expression<Func<T, int>> identityExpression,
Dictionary<int, T> dictionary)
{
_identityExpression = identityExpression;
_dictionary = dictionary;
}
public BaseFakeRepository(Expression<Func<T, int>> identityExpression)
{
_identityExpression = identityExpression;
_dictionary = new Dictionary<int, T>();
}
public virtual T Get(int id)
{
return !_dictionary.ContainsKey(id) ? null : _dictionary[id];
}
public virtual IList<T> GetAll()
{
return _dictionary.Values.ToList();
}
public virtual IList<T> GetBy(string find, string property, bool exactMatch)
{
return _dictionary.Values.ToList().FindAll(x=>(exactMatch && x.GetType()
.GetProperty(property)
.GetValue(x, null).ToString().Equals(find)
|| (!exactMatch && (x.GetType().GetProperty(property).GetValue(x, null))
.ToString().Contains(find))));
}
public virtual T Add(T item)
{
var newKey = _dictionary.Count == 0 ? 1 : _dictionary.Keys.Max() + 1;
SetIdentityValue(item, newKey);
_dictionary.Add(newKey, item);
return item;
}
public virtual T Update(T item)
{
var identityValue = GetIdentityValue(item);
if (!_dictionary.ContainsKey(identityValue))
{
throw new Exception(“Cannot update”);
}
_dictionary[identityValue] = item;
return item;
}
public virtual T Save(T item)
{
var identityValue = GetIdentityValue(item);
return identityValue == 0 || !_dictionary.Keys.Contains(identityValue)
? Add(item) : Update(item);
}
public virtual IList<T> Save(IList<T> items)
{
var savedItems = new List<T>();
items.ToList().ForEach(x => savedItems.Add(Save(x)));
return savedItems;
}
public virtual bool Delete(int id)
{
_dictionary.Remove(id);
return true;
}
public virtual bool DeleteAll()
{
_dictionary = new Dictionary<int, T>();
return true;
}
protected virtual string GetIdentityName()
{
return ((MemberExpression)_identityExpression.Body).Member.Name;
}
protected virtual int GetIdentityValue(T item)
{
return (int) item.GetType().GetProperty(GetIdentityName()).GetValue(item, null);
}
protected virtual void SetIdentityValue(T item, object value)
{
item.GetType().GetProperty(GetIdentityName()).SetValue(item, value, null);
}
}
An Example of Usage
When using the base repository, we need some way to tell it which property will be used as the identity (key) on the entity object. The way I have provided is to specify a lambda expression, so that this is strongly typed. For example, if “Id” is the name of the identity property on the Account entity, then in AccountFakeRepository, you can provide a constructor like this:
public AccountFakeRepository() : base(x=>x.Id)
This then tells the base fake repository to use the property “Id” as the identity or key.
Looking Closer at how the Identity is Resolved
Looking at the method “GetIdentityName” you can see that the identity property is retrieved from the right hand side of the lambda expression, i.e.:
return ((MemberExpression)_identityExpression.Body).Member.Name;
The methods “GetIdentityValue”, and “SetIdentityValue” are then used to get and set, repectively, the identity values using reflection, i.e.:
Get:
return (int) item.GetType().GetProperty(GetIdentityName()).GetValue(item, null);
Set:
item.GetType().GetProperty(GetIdentityName()).SetValue(item,
value, null);
How to Test the Base Fake Repository Class
You may notice that the class is not marked as abstract, and there is a second constructor which has the dictionary as an additional parameter. Strictly speaking this should be an abstract class. However, I have written it this way in order toallow easy unit testing of the class. For example, in your unit test “SetUp” method, you can do something like this:
var accounts = GetFakeAccounts(); _baseFakeRepository = new BaseFakeRepository<Account>(x => x.Id, accounts);
You can then write a whole suite of tests against the BaseFakeRepository if you feel the need to prove that the fake methods work correctly.