Monday 3 February 2014

Reusing common mocking functionality using Moq

Last month I wrote how to mock a repository in a generic way using mocking framework Moq. The example I used to illustrate the scenario was a pure generic repository, let's see it again:
public interface IIdentityKey<Tkey>
{
    TKey Id { get; set; }
}

public interface IRepository<Tkey,TEntity> 
    where TEntity : IIdentityKey<Tkey>
{
    IQueryable<TEntity> All();
 
    TEntity FindBy(TKey id);
 
    TEntity Add(TEntity entity);
 
    void Update(TEntity entity);
 
    void Delete(TEntity entity);
}
However, in real life, this is not always achievable, sometimes we need specific repositories per entity, let's make a change to that example, for instance, adding a new field named GroupId to Person entity.
public class Person :  IIdentityKey<long>
{
    public long Id { get; set; }

    public string Name { get; set; }

    public string Email { get; set; }

    public long GroupId { get; set; }
}
Thus, the new repository would need a new method named GetByGroup, but only for this repository, hence the new repository interface looks like this:
public interface IPersonRepository : IRepository<long, Person>
{
    IQueryable<Person> GetByBroup(long groupId); 
}
When trying to mock the behaviour it's more or less the same as in previous example except for the fact that we have an additional method GetByGroup, so it's not fair having to implement or even worst, copy and paste the boilerplate previously implemented. We need some way to set up the common behaviour to any inheritor of IRepository<TK,TE>. However, an object of type Mock<IPersonRepository> can not be assigned to an object of type Mock<IRepository<TK,TE>>. What to do?

Well, the class Mock<T> inherits from Mock without generics, we can create a method that accepts a Mock as parameter, but how do we treat that parameter as concrete typed object? Fortunately, the Mock class contains a method As<T> which returns the mock as a typed object specified in generic argument.

Finally, the rest is only to move the common set up to that new method, here is my sample:
public static void SetupRepositoryMock<TK, TE>(Mock mockRepo, List<TE> data)
    where TE : class, IIdentityKey<TK>
{
    var mock = mockRepo.As<IRepository<TK, TE>>();

    // setup All method
    mock.Setup(x => x.All()).Returns(data.AsQueryable());

    // setup Add method
    mock.Setup(x => x.Add(It.IsAny<TE>()))
        .Returns(new Func<TE, TE>(x =>
        {
            dynamic lastId = data.Last().Id;
            dynamic nextId = lastId + 1;
            x.Id = nextId;
            data.Add(x);
            return data.Last();
        }));

    // setup Update method
    mock.Setup(x => x.Update(It.IsAny<TE>()))
        .Callback(new Action<TE>(x =>
        {
            var i = data.FindIndex(q => q.Id.Equals(x.Id));
            data[i] = x;
        }));

    // setup FindBy (id)
    mock.Setup(x => x.FindBy(It.IsAny<TK>()))
        .Returns(new Func<TK, TE>(
            x => data.Find(q => q.Id.Equals(x))
        ));

    // setup Delete
    mock.Setup(x => x.Delete(It.IsAny<TE>()))
        .Callback(new Action<TE>(x =>
        {
            var i = data.FindIndex(q => q.Id.Equals(x.Id));
            data.RemoveAt(i);
        }));
}
Now, our method CreateController would look like this.
private PersonController CreateController()
{
    // create the mock to specific repository
    var mock = new Mock<IPersonRepository>();

    // set up the common methods 
    SetupRepositoryMock<long, Person>(mock, _fakedata);

    // start mocking specific methods
    mock.Setup(x => x.GetByBroup(It.IsAny<long>()))
        .Returns(new Func<long, IQueryable<Person>>(
            gid => _fakedata.Where(x => x.GroupId == gid).AsQueryable())
        );

    PersonController target = new PersonController(mock.Object);
    return target;
}
As the goal was only to implement the mock for the specific method to the repository interface, it was achieved by invoking SetupRepositoryMock<TK,TE> for common base methods and followed by the implementation of specific method. The full sample source code can be downloaded here.

Sunday 19 January 2014

Mocking a repository using Moq

Some time ago, I wrote about how to mock a repository in a generic way, so the it behaves accordingly using the supplied fake data which is no more than a list of objects of the same type of the repository we are mocking, of course. When I did that, I used RhinoMocks as mocking framework and I confess I'm a big fan of that as I consider it very versatile and powerful, but after having read this news about the current state of RhinoMocks, I decided to switch to another one.

I'm not trying to say that as soon as a good project is left behind from its creator, it means that the users should go away from it, as Ayende says as for this goal, it's done, in my opinion that latest release of RhinoMocks could be useful for the next 5 years. The new owner seems to have good ideas for the next versions of RhinoMocks. However, the community and life in general is moving at a different speed and sometimes we have to find a substitute even if we like the current one item.

According to the community, after some research on the internet and based on several well-documented stackoverflow answers, Moq is the best alternative, it's based on Linq and Expressions and it can be used in very simple ways which is good for the increasing amount of developers who are starting to use TDD or just trying to automate some tests.
Let's refresh the simple repository interfaces to be mocked:
public interface IIdentityKey<Tkey>
{
    TKey Id { get; set; }
}
public interface IRepository<Tkey,TEntity> where TEntity : IIdentityKey<Tkey>
{
    IQueryable<TEntity> All();
 
    TEntity FindBy(TKey id);
 
    TEntity Add(TEntity entity);
 
    void Update(TEntity entity);
 
    void Delete(TEntity entity);
}
In our controller we use this interface as it will be injected using any IoC such as Ninject, but important here is that the controller doesn't know or even cares the actual implementation of this repository, this is a fragment of our controller:
public class PersonController : ApiController
{
    private readonly IRepository<long, Person> _repository;  
 
    public PersonController(IRepository<long, Person> repository)
    {
        _repository = repository;
    }
 
    // GET api/person
    public IEnumerable<Person> Get()
    {
        return _repository.All().ToArray();
    }
 
    // the rest of the code removed for brevity ...
}
We need to create the 5 methods previously mentioned in the interface in a way that they make the operations on a list with initial data, such as this:
private List<Person> _fakedata = new List<Person> {
    new Person { Id = 1, Name = "Person1", Email = "person1@nomail.com" },
    new Person { Id = 2, Name = "Person2", Email = "person2@nomail.com" },
    //  ( ... )
    new Person { Id = 8, Name = "Person8", Email = "person8@nomail.com" }
};
Let's start with the actual mock creation and set up now using Moq
private IRepository<TK, TE> CreateRepository<TK, TE>(List<TE> data)
    where TE : class, IIdentityKey<TK>
{
    var mock = new Mock<IRepository<TK, TE>>();

    // all the mocking setup goes here ...

    return mock.Object;
}
The actual mock procedure is made through the combination of Setup(...).Returns(...) and Setup(...).Callback(...) for methods that return something and void respectively. The All() method is done this way.
// setup All method
mock.Setup(x => x.All()).Returns(data.AsQueryable());
The Returns() method accepts an object of the same type as the return type in Setup() argument or a Func with return type the same as declared in Setup, so it matches the signature at runtime. In that example it's just return the raw list previously declared.
// setup Add method
mock.Setup(x => x.Add(It.IsAny<TE>()))
    .Returns(new Func<TE, TE>(x => {
        dynamic lastId = data.Last().Id;
        dynamic nextId = lastId + 1;
        x.Id = nextId;
        data.Add(x);
        return data.Last();
    }));
The Add() method is implemented using a bit more complex behaviour in order to simulate the auto incremental in database helped by dynamics for not to force a concrete type as in C# there's no generic constraint for only numeric types.
// setup Update method
mock.Setup(x => x.Update(It.IsAny<TE>()))
    .Callback(new Action<TE>(x =>
    {
        var i = data.FindIndex(q => q.Id.Equals(x.Id));
        data[i] = x;
    }));

// setup FindBy (id)
mock.Setup(x => x.FindBy(It.IsAny<TK>()))
    .Returns(new Func<TK, TE>(
        x => data.Find(q => q.Id.Equals(x))
    ));

// setup Delete
mock.Setup(x => x.Delete(It.IsAny<TE>()))
    .Callback(new Action<TE>(x => {
        var i = data.FindIndex(q => q.Id.Equals(x.Id));
        data.RemoveAt(i);
        }
    ));

Following the same idea, we've got the remaining methods from the interface implementation. Earlier I mentioned a generic method which accepts two arguments: TK and TE related to type of key and of entity, now it will be called by another method for this specific controller.
        
private PersonController CreateController()
{
    IRepository<long, Person> repo = CreateRepository<long, Person>(_fakedata);
    PersonController target = new PersonController(repo);
    return target;
}
Finally, the test should look like this fragment:
  
[TestMethod]
public void Get()
{
    // Arrange
    PersonController controller = CreateController();

    // Act
    IEnumerable<Person> result = controller.Get();

    // Assert
    Assert.IsNotNull(result);
    Assert.AreEqual(8, result.Count());
    Assert.AreEqual("Person1", result.ElementAt(0).Name);
    Assert.AreEqual("Person8", result.ElementAt(7).Name);
}

[TestMethod]
public void GetById()
{
    // Arrange
    PersonController controller = CreateController();

    // Act
    Person result = controller.Get(5);

    // Assert
    Assert.AreEqual("Person5", result.Name);
}
We invoke the CreateController method on each test so the logic previously described is encapsulated and then a new instance of the controller with the mocked repository inside. The sample code can be downloaded here.