41

I am creating a repository that exposes IQueryable. What is the best way to mock this out for my unit testing?

Since I am using RhinoMocks for the rest of my mock objects, I tried to do the following:

IQueryable<MyObject> QueryObject = 
    MockRepository.GenerateStub<IQueryable<MyObject>>();

This doesn't work though so I tried doing this:

IQueryable<MyObject> QueryObject = 
    (new List<MyObject> { new MyObject() }).AsQueryable();

Is there a better way to do this, or have any other mocking frameworks built support for IQueryable in?

My repository interface looks like this:

public interface IRepository<T> where T : TableServiceEntity
{
    IQueryable<T> Table { get; }
    void Attach(T existingItem);
    void Delete(T itemToDelete);
    void Insert(T newItem);
    T Load(string partitionKey, string rowKey);
    IEnumerable<T> Load(string partitionKey);
    IEnumerable<T> Query(IQueryable<T> query);
    IEnumerable<T> Last(int count);
    T Last();
    void Update(T item);
}

Here is the method that I want to test:

public Post LoadPost(int year, int month, int day, string slug)
{
    var query = from p in _blogRepository.Table
                where 
                    p.PartitionKey == Key.Partition(year, month, day) 
                    && p.Slug == slug
                select p;

    var posts = _blogRepository.Query(query.Take(1));

    return posts.First();
}

Then here is the test as I have it right now that will test LoadPost.

[Fact]
public void LoadWillRetrieveByPartitionKeyAndRowKeyWhenUsingUriFormat()
{
    Repository
        .Stub(x => x.Query(Arg<IQueryable<Post>>.Is.Anything))
        .Return(new List<Post> {_post});

    var result = Service.LoadPost(
                            _post.Year(),
                            _post.Month(), 
                            _post.Day(), 
                            _post.Slug);

    Assert.NotNull(result);
}

The code is taken from my AzureBlog project.

Aaron Weiker
  • 2,523
  • 2
  • 21
  • 22

4 Answers4

10

I usually do exactly what you ended up doing in your test. When writing my tests I assume that the .Net library classes work correctly and don't contain bugs, so I can use them in the tests. When I need a test list, collection, queryable, dictionary, etc. I just create the real thing and populate with test data. It makes the tests much more readable and quicker to write, and to be honest the risk is non-existent.

Grzenio
  • 35,875
  • 47
  • 158
  • 240
5

If you want to mock out your repository, you won't be mocking IQueryable. Instead, mock out the methods of your repository to return fixed, known values (like your second example) that can be used to run your unit tests.

PatrickSteele
  • 14,489
  • 2
  • 51
  • 54
  • I had started down that route and then ended up with creating an extra layer of a specific repository over a generic repository. This resulted in my Domain Service -> Domain Repository -> Generic Repository. If I'm able to go from Domain Service -> Generic Repository and still be testable without implementation details leaking into the Domain Service I would be a lot happier as it's less code that needs to be maintained and tested. – Aaron Weiker Feb 12 '10 at 04:36
  • I see what you're saying. But if your question arose from writing unit tests for your DomainService, then I think you should be mocking the DomainRepository and don't worry about the Generic Repository (for right now). Unit testing the DomainService is best accomplished by mocking it's dependencies. As far as the DomainService goes, it shouldn't care how DomainRepository is implemented (i.e. inheriting from a base class). Hope this helps! – PatrickSteele Feb 12 '10 at 18:13
2

I know this is an old question, but just want to add my 2 cents.

I had the same issue with the repositories generated with SharpLite, which is a ASP .NET MVC framework I use from time to time. After some time, I found out a solution, the only issue is that is using Moq, and not Rhino Mocks, but possibly you can find a way to adapt it. I made a blog post here on how to do it.

It's basically creating a list that implements IQueryable and using it as a fake data background. Hope I can help!

David Conde
  • 4,631
  • 2
  • 35
  • 48
  • 1
    Never provide a link to anywhere without providing an example...your blog is gone. – UNeverNo Nov 22 '21 at 13:38
  • 1
    No defence there! That was a long time ago and even though I stopped using .NET maybe 5 - 6 years ago, I imagine things have moved and it probably isn't best practice anymore – David Conde Nov 23 '21 at 14:08
  • Now we'll never know. Well, you will. – Red Nov 30 '21 at 17:21
  • https://web.archive.org/web/20180715001608/http://davidcondemarin.blogspot.com/2012/07/testing-sarp-lite-repositories-with-moq.html – Rolf Kristensen Feb 26 '22 at 21:55
0

I’m not sure if this will help you… but I did something like what you are talking about. In my scenario, I had a data context class that used the repository.

I started off by creating an interface (IRepository) that included the IQueryable method. Then I created two classes that implement this interface. One class uses an ORM for data manipulation (DbEntityRepository) and another class uses a class property (MemoryRepository). The data context class had a constructor that required the IRepository. Doing this I could use the MemoryRepository for when Testing the data context and I could use the DbEntityRepository for the Application.

If you are interested… you can find the code on codeplex: IQToolkitContrib

Tom Brothers
  • 5,929
  • 1
  • 20
  • 17