【发布时间】:2012-10-31 04:26:58
【问题描述】:
我目前正在为 MVC4 应用程序中的存储库实现编写单元测试。为了模拟数据上下文,我首先采用了this post 的一些想法,但现在我发现了一些限制,这让我怀疑是否可以正确模拟IQueryable。
特别是,我看到了一些测试通过但代码在生产中失败的情况,我无法找到任何方法来模拟导致此失败的行为。
例如,以下 sn-p 用于选择属于预定义类别列表的Post 实体:
var posts = repository.GetEntities<Post>(); // Returns IQueryable<Post>
var categories = GetCategoriesInGroup("Post"); // Returns a fixed list of type Category
var filtered = posts.Where(p => categories.Any(c => c.Name == p.Category)).ToList();
在我的测试环境中,我尝试使用上面提到的假的DbSet 实现来模拟posts,并且还通过创建Post 实例的List 并使用AsQueryable() 将其转换为IQueryable扩展方法。这两种方法都在测试条件下工作,但代码实际上在生产中失败,除了以下例外:
System.NotSupportedException : Unable to create a constant value of type 'Category'. Only primitive types or enumeration types are supported in this context.
虽然这样的 LINQ 问题很容易解决,但真正的挑战是找到它们,因为它们不会在测试环境中暴露出来。
我是否不切实际地期望我可以模拟 Entity Framework 的 IQueryable 实现的行为?
感谢您的想法,
提姆。
【问题讨论】:
-
这不是单元测试,但如果您执行 ToString()(在 DbQuery 上)或 ToTraceString()(在 ObjectQuery 上)会怎样?它将转储与您的查询相对应的 SqlQuery,这意味着它将通过整个 EF 查询管道,但不会将查询发送到数据库。它应该揭示这样的案例。
-
@Pawel。谢谢 - 这是朝着正确方向迈出的一大步,尽管如果我能以某种方式自动化它会很好。
标签: entity-framework mocking iqueryable