Testing S#arp Lite Repositories with Moq

1 comments

One pending matter I've always had is to improve my testing skills, there I said it. I test, but not as much as I should. When I say test, I mean Unit Test, not just test the application by launching it and starting to poke it. One thing that I found to be a really outstanding idea with S#arp Lite is that repositories eliminated many complications. If you had a repository and needed to run a query against it, just call GetAll and throw some Linq at. Grated, it assumed that the Linq provider for the underlaying data model was mature, but with NHibernate and EntityFramework being the two ORM of my choice always, that seems like a fair assumption.

However, this has a downside, I tried to test the repositories and had a really rough time getting to test a repo that was using an underlying IQueryable item. However, this became quite clear with time, and now I can test my repos. Let's make a fairly simple test scenario. Let's assume I have a user class, with a few standard properties, pretty much like this one:

public class User : Entity
{
 public virtual string Password { get; set; }

 public virtual string Email { get; set; }

 public virtual bool Blocked { get; set; }

 public virtual int LoginCount { get; set; }
} 

Now, I have a class called Membership that handles my Membership logic, that is, logging users, blocking them after a couple of bad logins, etc. That class should look like this:

public class Membership
{
 IRepository<User> _usersRepository;

 public Membership( IRepository<User> usersRepository )
 {
  _usersRepository = usersRepository;
 }
 
 public bool IsValidUser( string email, string password )
 {
  //create test first!
  return false;
 }
} 

Now, we need to create a test case. Let's call it, MembershipTests

[TestFixture]
public class MembershipTests
{
 [TestFixtureSetUp]
 public void SetupTestEnvironment()
 {
 
 }
}

Now, I want to create a Mock repository to pass it along to my test Membership class, but I need to do it so that it simulates the data backed without touching my actual data nor getting too slow. Obviously we need a list, but not just any list, we need a list that can pose for a Repository or at least fake it. That's why we need to create this sort of list, a QueryableList:

public class QueryableList<T, TId> : List<T>, IQueryable<T> where T : EntityWithTypedId<TId>
{
 #region Constructors
 public QueryableList()
 { }

 public QueryableList(IEnumerable<T> source)
  : base(source)
 { } 
 #endregion

 #region IQueryable<T> implementation
 public Expression Expression
 {
  get { return ToArray().AsQueryable().Expression; }
 }

 public Type ElementType
 {
  get { return typeof(T); }
 }

 public IQueryProvider Provider
 {
  get { return ToArray().AsQueryable().Provider; }
 }
 #endregion

 public void UpdateEntity(T entity)
 {
  var index = -1;

  for (var i = 0; i < Count; i++)
   if (this[i].Equals(entity))
    index = i;

  if (index == -1)
   Add(entity);
  else
   this[index] = entity;
 }
} 

Voila! We have a List that directly implements IQueryable, which is a good thing, not a hard thing to do, but it will help us a lot. We need to get the entity of the List and the Id that is going to be used on the list to keep it as generic as possible, so when we need to test a repo of entities with typed id's, we won't have to rewrite much. The UpdateEntity method will mimic the SaveOrUpdate method we have on our repo using the Equals method to invoke the Equality comparer provided by S#arp Lite. Now, we need to setup our Mocks. We go back to the TestSetup and let's setup our environment:

[TestFixture]
public class MembershipTests
{
 private Membership _membership;
 
 [TestFixtureSetUp]
 public void SetupTestEnvironment()
 {
  var usersMockedRepo = new Mock<IRepository<User>>();
  
  var users = new List<User> { new User{ Blocked = false, Email = "david@someplace.com", Password = "a password" } };
  var list = new QueryableList<T, int>(users);
  
  //Mock GetAll
  usersMockedRepo.Setup(x => x.GetAll()).Returns(list);
  
  //Mock the Get
  usersMockedRepo.Setup( x => x.Get( It.IsAny<int>() ))
      .Returns( (int id) => list.AsQueryable()
      .SingleOrDefault(x => x.Id.Equals(id)));
  
  //Mock the SaveOrUpdate using our own
  usersMockedRepo.Setup(x => x.SaveOrUpdate(It.IsAny<T>()))
      .Callback((T entity) => list.UpdateEntity(entity));
      
  //Mock the delete
  usersMockedRepo.Setup(x => x.Delete(It.IsAny<T>())).Callback((T entity) => list.Remove(entity));
  _membership = new Membership(usersMockedRepo.Object);
 }
}

Now, we have setup our very own mocked repository. We need to make a test now for the IsValidUser method we left before. Let's write a simple test case:

[TestCase]
public void CheckBasicAuthentication()
{
 var checkValidUser = Membership.Instance.IsValidUser("david.conde@gmail.com", "a password");
 var checkInvalidUser = Membership.Instance.IsValidUser("david.conde@gmail.com", "another password");

 Assert.AreEqual(checkInvalidUser, false);
 Assert.AreEqual(checkValidUser, true);
}

And that's it! We have our own test and we can now create as many test cases as we want all relying on a simple structure like a list. There is one final thought here, which came to mind while reading this StackOverflow post. The idea is to put the setup into a helper method, so we can reuse it with different test scenarios:

Please note that the following code can induce headaches :)

public static class MockExtensions
{
 public static void SetupIQueryableTypedRepository<T, TId>
  (this Mock<IRepositoryWithTypedId<T, TId>> mockObject, IEnumerable<T> source)
  where T : EntityWithTypedId<TId> where TId : IComparable
 {
  var list = new QueryableList<T, TId>(source);

  mockObject.Setup(x => x.GetAll()).Returns(list);
  mockObject.Setup(x => x.Get(It.IsAny<TId>())).Returns((TId id) => list.AsQueryable().SingleOrDefault(x => x.Id.Equals(id)));

  mockObject.Setup(x => x.SaveOrUpdate(It.IsAny<T>())).Callback((T entity) => list.UpdateEntity(entity));
  mockObject.Setup(x => x.Delete(It.IsAny<T>())).Callback((T entity) => list.Remove(entity));
 }

 public static void SetupIQueryableRepository<T>(this Mock<IRepository<T>> mockObject, IEnumerable<T> source)
  where T : Entity
 {
  var list = new QueryableList<T, int>(source);

  mockObject.Setup(x => x.GetAll()).Returns(list);
  mockObject.Setup(x => x.Get(It.IsAny<int>())).Returns( (int id) => list[id] );
  
  mockObject.Setup(x => x.SaveOrUpdate(It.IsAny<T>())).Callback( (T entity) => list.UpdateEntity(entity) );
  mockObject.Setup(x => x.Delete(It.IsAny<T>())).Callback((T entity) => list.Remove(entity));
 }
}

Now, we can reduce our Setup method to this:

[TestFixtureSetUp]
public void SetupTestEnvironment()
{
 var usersMockedRepo = new Mock<IRepository<User>>();
 var users = new List<User> { new User{ Blocked = false, Email = "david@someplace.com", Password = "a password" } };
 
 usersMockedRepo.SetupIQueryableRepository(users);
 _membership = new Membership(usersMockedRepo.Object);
}

If you just want to be able to test your S#arp Lite repositories using this, then just get this extension to your code, set your mocked repositories using this idea and done! If you have any other thoughts, let me know on the comments!