How do I mock IQueryable<T>

别等时光非礼了梦想. 提交于 2019-12-03 11:31:51

问题


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.


回答1:


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.




回答2:


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.




回答3:


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!




回答4:


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



来源:https://stackoverflow.com/questions/2242534/how-do-i-mock-iqueryablet

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!