我如何模拟 IQueryable

发布于 2024-08-21 06:02:15 字数 1932 浏览 10 评论 0原文

我正在创建一个公开 IQueryable 的存储库。为我的单元测试模拟这个的最佳方法是什么?

由于我将 RhinoMocks 用于其余的模拟对象,所以我尝试执行以下操作:

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

但这不起作用,所以我尝试这样做:

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

是否有更好的方法来执行此操作,或者有任何其他模拟框架内置支持I可查询?

我的存储库界面如下所示:

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);
}

这是我要测试的方法:

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();
}

然后这是我现在拥有的将测试 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);
}

该代码取自我的 AzureBlog 项目。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

战皆罪 2024-08-28 06:02:15

我通常会按照你在测试中最终做的事情做。在编写测试时,我假设 .Net 库类工作正常并且不包含错误,因此我可以在测试中使用它们。当我需要测试列表、集合、可查询、字典等时,我只需创建真实的东西并填充测试数据。它使测试更具可读性并且编写起来更快,而且说实话,风险是不存在的。

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.

栀子花开つ 2024-08-28 06:02:15

如果您想模拟您的存储库,则不会模拟 IQueryable。相反,模拟存储库的方法以返回可用于运行单元测试的固定已知值(如第二个示例)。

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.

撞了怀 2024-08-28 06:02:15

我知道这是一个老问题,但只想补充我的 2 美分。

我对使用 SharpLite 生成的存储库也有同样的问题,SharpLite 是我不时使用的 ASP .NET MVC 框架。一段时间后,我找到了一个解决方案,唯一的问题是使用 Moq,而不是 Rhino Mocks,但也许你可以找到一种方法来适应它。我在博客文章上怎么做。

它基本上是创建一个实现 IQueryable 的列表并将其用作虚假数据背景。希望我能帮忙!

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!

柠北森屋 2024-08-28 06:02:15

我不确定这是否会对您有帮助……但我做了类似您所说的事情。在我的场景中,我有一个使用存储库的数据上下文类。

我首先创建一个包含 IQueryable 方法的接口 (IRepository)。然后我创建了两个实现这个接口的类。一个类使用 ORM 进行数据操作 (DbEntityRepository),另一个类使用类属性 (MemoryRepository)。数据上下文类有一个需要 IRepository 的构造函数。这样做时,我可以在测试数据上下文时使用 MemoryRepository,并且可以将 DbEntityRepository 用于应用程序。

如果您有兴趣...您可以在 codeplex 上找到代码:IQToolkitContrib

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文