I decided to start writing unit tests in our application. It uses Entity Framework with a repository pattern.
Now I want to start testing logic classes which are using the repositories. I provide a simple example here.
Three of my methods in the class GenericRepository:
public class GenericRepository : IRepository
{
    public IQueryable<TEntity> GetQuery<TEntity>() where TEntity : class
    {
        var entityName = GetEntityName<TEntity>();
        return Context.CreateQuery<TEntity>(entityName);
    }
    private string GetEntityName<TEntity>() where TEntity : class
    {
        return typeof(TEntity).Name;
    }
    public IEnumerable<TEntity> Find<TEntity>(Expression<Func<TEntity, bool>> predicate) where TEntity : class
    {
        return GetQuery<TEntity>().Where(predicate).AsEnumerable();
    }
}
A simple logic class returning distinct years from a calendar table in descending order (yes I know the word calendar is misspelled in our code):
public class GetDistinctYearsFromCalendar
{
    private readonly IRepository _repository;
    public GetDistinctYearsFromCalendar()
    {
        _repository = new GenericRepository();
    }
    internal GetDistinctYearsFromCalendar(IRepository repository)
    {
        _repository = repository;
    }
    public int[] Get()
    {
        return _repository.Find<Calender_Tbl>(c => c.Year.HasValue).Select(c => c.Year.Value).Distinct().OrderBy(c => c).Reverse().ToArray();
    }
}
And here is my first test:
[TestFixture]
public class GetDistinctYearsFromCalendarTest
{
    [Test]
    public void ReturnsDistinctDatesInCorrectOrder()
    {
        var repositoryMock = new Mock<IRepository>();
        repositoryMock.Setup(r => r.Find<Calender_Tbl>(c => c.Year.HasValue)).Returns(new List<Calender_Tbl>
        {
           new Calender_Tbl
              {
                  Date =
                      new DateTime(2010, 1, 1),
                  Year = 2010
              },
           new Calender_Tbl
              {
                  Date =
                      new DateTime(2010, 2, 1),
                  Year = 2010
              },
           new Calender_Tbl
              {
                  Date =
                      new DateTime(2011, 1, 1),
                  Year = 2011
              }
        }.AsQueryable());
        var getDistinct = new GetDistinctYearsFromCalendar(repositoryMock.Object).Get();
        Assert.AreEqual(2, getDistinct.Count(), "Returns more years than distinct.");
        Assert.AreEqual(2011, getDistinct[0], "Incorrect order, latest years not first.");
        Assert.AreEqual(2010, getDistinct[1], "Wrong year.");
    }
}
This is working fine. But this is not actually what I want to do. Since I have to setup the method Find on the mock object I also need to know how it is going to be called in my logic class. If I would like to do TDD I don't want to mind about this. All I want to know is which Calendar entities my repository should provide. I would like to setup the GetQuery method. Like this:
repositoryMock.Setup(r => r.GetQuery<Calender_Tbl>()).Returns(new List<Calender_Tbl>
{
  new Calender_Tbl
      {
          Date =
              new DateTime(2010, 1, 1),
          Year = 2010
      },
  new Calender_Tbl
      {
          Date =
              new DateTime(2010, 2, 1),
          Year = 2010
      },
  new Calender_Tbl
      {
          Date =
              new DateTime(2011, 1, 1),
          Year = 2011
      }
}.AsQueryable());
So when Find is calling GetQuery internally in the GenericRepository class it should get the correct Calendar entities that I setup in GetQuery. But this is not working of course. Since I haven't setup the Find method of my mock object I don't get any entities.
So what to do? Of course I could probably use Moles or some other framework which mocks everything but I don't want to do that. Is there anything I can do in the design of the class or test to solve the issue?
It is not the end of the world if I have to go with my current solution but what if the property year turns into a not nullable int? Then of course I will have to change my implementation in the logic class but I would also have to change the test. I would like to try to avoid this.