views:

162

answers:

4

Getting started with TDD and the repository pattern, I'm wondering if it makes any sense testing this...

Using the repository pattern, I have this interface:

public interface ICustomerRepository
{
    IList<Customer> List();
    Customer Get(int id);
}

I have like 50 different entities, so 50 different repository interfaces/implementations.

My question is if it's correct to test each repository, by mocking up the interface, like:

[TestMethod]
public void List_Should_Return_Two_Customers()
{
    // Arrange
    var customerr = new List<Customer>();
    customer.Add(new Customer());
    customer.Add(new Customer());

    var repository = new Mock<ICustomerRepository>();
    repository.Setup(r => r.List()).Returns(customer);

    // Assert
    Assert.AreEqual(2, repository.Object.List().Count);
}

[TestMethod]
public void Get_Should_Return_One_Customer()
{
    // Arrange
    var customer = new List<Customer>();
    customerr.Add(new Customer() { Id = 1 });
    customerr.Add(new Customer() { Id = 2 });

    var repository = new Mock<ICustomerRepository>();
    repository.Setup(r => r.Get(1)).Returns(customer.Where(w => w.Id == 1).First());

    // Assert
    Assert.IsTrue(repository.Object.Get(1).Id == 1);
}

Does it make any sense testing a fake implementation of these interfaces? To me it does not.

A: 

Yes, it is "correct" to test each Repository. Repositories exist to abstract your database away from the code, and should be verified that they are working correctly. Your data access layer is arguably one of the most important components to test.

womp
So the two tests I wrote are actually correct? Would it be a good idea to create fake repository classes like FakeCustomerRepository with actually customer data in it? And then use that implementation in my tests?
Tommy Jakobsen
Yes, but, you should not test the mocks. (This is what Tommy asks, should I test the mocks; the answer to me is no).I would indeed test the real implementations, but not the fake ones.
Frederik Gheysels
In other tests, in where you need a repository, you could / should use a fake implementation, since those tests test something else, and not the implementation of the 'real' repository
Frederik Gheysels
So Frederik, would you create "real" implementations with fake data for each repository?
Tommy Jakobsen
I see there are actually two questions in the question. Guess I answered the wrong one :(
womp
+2  A: 

No, it does not make sense. Obviously you should test only implementations, not interfaces. There is nothing to test in an interface.

The only things being tested in your examples are the mocking framework, the .NET list and some LINQ extension methods. There is no need to test those, somebody else already takes care of that.

Maybe the intention was to provide unit tests for the fact that the interface exists and has certain methods? In that case, the tests are still unnecessary. This is implicitly tested by the tests for other code that relies on the interface declaration.

You should only create an ICustomerRepository mock when you need a fake implementation in order to test other code.

Wim Coenen
A: 

The others are right. You can't test interfaces. You are in fact testing mocks, and that doesn't make sense. Usually I test repositories against a database, so, not so much unit testing for them. And for testing anything above them I mock them. Keep in mind that 50 types of entities doesn't mean 50 repositories.

Regards.

Fredy Treboux
A: 

Can I propose an alternate solution... As Simple as your Repository is (if they are all the same methods except for what they return) why don't you make a base class using Generics. Then you would only have to test the base class.

public interface IRepository<TEntity> where TEntity : class
{
    IList<TEntity> List();
    TEntity Get(int id);
}

public abstract class BaseRepository<TEntity> : IRepository<TEntity> where TEntity : class
{
    IList<TEntity> List()
    {
        //DataContext.GetTable<TEntity>().ToList();
    }

    TEntity Get(int id)
    {
        //Might have to do some magic here... you can use reflection or create
        //an abstract method that the derived class must override that returns
        //a delegate id selector.
    }
}
J.13.L
I've had some trouble making my repositories generic. It worked but in the end wasn't as elegant as I would have liked. Bu for the Get(id) method the solution I'd recommend is 'where TEntity : IdEntity' or similar, with IdEntity being a real class that has an Id property and other persistence information.