Click here to Skip to main content
12,503,198 members (66,738 online)
Click here to Skip to main content
Add your own
alternative version

Tagged as

Stats

15.3K views
8 bookmarked
Posted

Mocking the generic repository

, 29 Jul 2012 CPOL
Rate this:
Please Sign up or sign in to vote.
This post describes one possible way to mock the generic repository. This can be useful when isolating the application from the database, usually inside unit tests. Another possible usage might be the creation of "portable" version of your application.
This post describe one way to mock the generic repository. It assumes that you are familiar with the
Service <-> Repository <-> Database architecture.
Another pre-requisity is the knowledge of the repository pattern and it's generic variant.

In the majority of my projects I am using the following generic repository class.
public interface IRepository
{
 T Load<T>(object id);
 T Get<T>(object id);
 IEnumerable<T> Find<T>(Expression<Func<T, bool>> matchingCriteria);
 IEnumerable<T> GetAll<T>();
 void Save<T>(T obj);
 void Update<T>(T obj);
 void Delete<T>(T obj);
 void Flush();
 int CountAll<T>();
 void Evict<T>(T obj);
 void Refresh<T>(T obj);
 void Clear();
 void SaveOrUpdate<T>(T obj);
}

Based on this technique, some people decide to implement concrete classes of this interface (CarRepository : IRepository), whereas others decide to keep using the generic implementation. That depends on the ORM that you are using. With EF and NHibernate you can easily implement the generic variant of the repository (check the links).

I am also using the generic variant (mostly with NHibernate). Now the question is: How to mock this generic repository? It can be a bit tricky to mock. When you have one class for each repository which works for one concrete type you can mock the repository quite easily. For example StudentRepository which handles entities of type Student might be backed up a list of students.

While when working with generic repository, it might be a bit harder. Here is how I have solved the problem:

public class MockedRepository :IRepository
{
 public MockedRepository()
 {
  cities = DeserializeList<city>("CityDto");
  stations = DeserializeList<station>("StationDto");
  tips = DeserializeList<informationtip>("InformationTipDto");
  countries = DeserializeList<country>("CountryDto");
  
  dataDictionary = new Dictionary<type,object>();
  dataDictionary.Add(typeof(City), cities);
  dataDictionary.Add(typeof(Station), stations);
  dataDictionary.Add(typeof(InformationTip), tips);
  dataDictionary.Add(typeof(Country), countries);
  }   

 public T Get<T>(object id)
 {
  Type type = typeof(T);
  var data = dataDictionary[type];
  IEnumerable<T> list = (IEnumerable<T>)data;
  var idProperty = type.GetProperty("Id");
  return list.FirstOrDefault(x=>(int)idProperty.GetValue(x,null) == (int)id);
 }

 public IEnumerable<T> Find<T>(Expression<Func<T, bool>> matchingCriteria)
 {
  Type type = typeof(T);
  var data = dataDictionary[type];
  IEnumerable<T> list = (IEnumerable<T>)data;
  var matchFunction = matchingCriteria.Compile();
  return list.Where(matchFunction);
 }

 public IEnumerable<T> GetAll<T>()
 {
  Type type = typeof(T);
  return (IEnumerable<T>)dataDictionary[type];
 }

 public void Save<T>(T obj)
 {
  Type type = typeof(T);
  List<T> data = (List<T>)dataDictionary[type];
  data.Add(obj);
 }
}
The main building block of this mocked repository is the dictionary which contains for each type in the repository the enumerable collection of objects. Each method in the mocked repository can use this dictionary to determine which is the collection addressed by the call (by using the generic type T.).
Type type = typeof(T);
var data = dataDictionary[type];
IEnumerable<T> list = (IEnumerable<T>)data;
Now what to do next, depends on each method. I have shown here only the methods which I needed to mock, but the other ones should not be harded to mock. The most interesting is the Find method, which takes as the parameter the matching criteria. In order to pass this criteria to the Where method on the collection, this criteria (represented by an Expression) has to be compiled into a predicate Func

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Jan Fajfr
Software Developer (Junior) OCTO Technology
Czech Republic Czech Republic
Writing software at ITG RFQ-hub.
LinkedIn
Blog
GitHub
Articles at OCTO blog

You may also be interested in...

Comments and Discussions

 
Questionrequest link for download Pin
pop ioana5-Mar-15 23:12
memberpop ioana5-Mar-15 23:12 
GeneralI may be missing something but why would you not do Pin
Sacha Barber10-Jul-12 5:18
mvpSacha Barber10-Jul-12 5:18 
GeneralRe: I may be missing something but why would you not do Pin
Jan Fajfr22-Jul-12 22:58
memberJan Fajfr22-Jul-12 22:58 
QuestionGood pattern, questions on change notification Pin
Topchris24-Jun-12 2:27
memberTopchris24-Jun-12 2:27 
AnswerRe: Good pattern, questions on change notification Pin
Jan Fajfr22-Jul-12 23:06
memberJan Fajfr22-Jul-12 23:06 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.160919.1 | Last Updated 29 Jul 2012
Article Copyright 2012 by Jan Fajfr
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid