Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET MVC - How to Unit Test boundaries in the Repository pattern?

Given a basic repository interface:

public interface IPersonRepository
{
    void AddPerson(Person person);
    List<Person> GetAllPeople();
}

With a basic implementation:

public class PersonRepository: IPersonRepository
{
    public void AddPerson(Person person) 
    {
        ObjectContext.AddObject(person);
    }

    public List<Person> GetAllPeople()
    {
        return ObjectSet.AsQueryable().ToList();
    }
}

How can you unit test this in a meaningful way? Since it crosses the boundary and physically updates and reads from the database, thats not a unit test, its an integration test.

Or is it wrong to want to unit test this in the first place? Should I only have integration tests on the repository?

I've been googling the subject and blogs often say to make a stub that implements the IRepository:

public class PersonRepositoryTestStub: IPersonRepository
{
    private List<Person> people = new List<Person>();
    public void AddPerson(Person person) 
    {
        people.Add(person);
    }

    public List<Person> GetAllPeople()
    {
        return people;
    }
}

But that doesnt unit test PersonRepository, it tests the implementation of PersonRepositoryTestStub (not very helpful).

like image 496
JK. Avatar asked May 13 '10 00:05

JK.


2 Answers

In this specific case I think you don't need to make a unit test for your repository class, as the implementation is simply invoking the ObjectContext object, so it will be like testing something you didn't build (which is not the idea). In case you don't have any complex logic, my recommendation is not to waste time on making a unit test for that class. What you say about the PersonRepositoryTestStub is a fake implementation of the repository for testing the layer that is above of your DAL.

like image 62
uvita Avatar answered Nov 15 '22 09:11

uvita


I have run into the same problem. I wrote a slew of unit tests against an implementation of my repository interface that was a fake repository. Shortly after completing it, I realized that I wrote the unit test to test the fake repository and I wrote the fake repository simply to support the unit tests. This seemed like a large amount of useless code.

I have come to the conclusion that I don't need the unit tests but that the fake repository implementation is good because I can use it as the repository my services (and therefore my controllers) use so that unit tests against those will be predictable (thanks to a predefined fake repository).

So, I have decided to leave the unit tests against the fake repository in there as they are helpful to test my fake repository so that I can be assured that the higher levels of my application are using fully tested fakes.

In other words, the fake repository and the unit tests against the fake repository are the "supporting cast" for higher levels of the applications and the unit tests against higher levels of the application.

Hope that helps.

like image 33
Brian McCord Avatar answered Nov 15 '22 10:11

Brian McCord