我如何模拟IQueryable <t> </t>

时间:2010-02-11 05:44:02

标签: c# mocking rhino-mocks iqueryable

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

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

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

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

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

有更好的方法可以做到这一点,还是有任何其他模拟框架构建了对IQueryable的支持?

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

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项目。

4 个答案:

答案 0 :(得分:10)

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

答案 1 :(得分:4)

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

答案 2 :(得分:2)

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

我对使用SharpLite生成的存储库存在同样的问题,SharpLite是我不时使用的ASP .NET MVC框架。过了一段时间,我发现了一个解决方案,唯一的问题是使用Moq,而不是Rhino Mocks,但可能你可以找到一种方法来适应它。我就如何做到了blog post here

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

答案 3 :(得分:0)

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

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

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