moq测试LINQ哪里查询

我使用EF 4.1构建域模型.我有一个具有Validate(string userCode)方法的Task类,其中我想确保用户代码映射到数据库中的有效用户,因此:
public static bool Validate(string userCode)
{
    IDbSet<User> users = db.Set<User>();
    var results = from u in users
              where u.UserCode.Equals(userCode)
              select u;
    return results.FirstOrDefault() != null;
}

我可以使用Moq来模拟IDbSet没问题.但是遇到麻烦的地方呼叫:

User user = new User { UserCode = "abc" };
IList<User> list = new List<User> { user };
var users = new Mock<IDbSet<User>>();
users.Setup(x => x.Where(It.IsAny<Expression<Func<User,bool>>>())).Returns(list.AsQueryable);

Initialization method JLTi.iRIS3.Tests.TaskTest.SetUp threw exception.
System.NotSupportedException: System.NotSupportedException: Expression 
references a method that does not belong to the mocked object:
x => x.Where<User>(It.IsAny<Expression`1>()).

除了创建一个间接级别(例如,使用ServiceLocator获取运行LINQ的对象,然后模拟该方法)我不能想到如何测试这个,但我想确保没有办法我介绍另一层.而且我可以看到这种LINQ查询需要很频繁,所以服务对象可以迅速地失控.

有可能有一点灵魂有帮助吗?谢谢!

据我所知,Moq只能设置虚拟对象本身的虚拟方法,但您正在尝试设置扩展(静态)方法 – 没有办法!这些方法绝对不在您的模拟范围之内.

此外,代码错误,难以测试.您需要进行大量初始化才能测试.改用:

internal virtual IQueryable<User> GetUserSet()
{
    return db.Set<User>();
} 

public bool Validate(string userCode)
{
    IQueryable<User> users = GetUserSet();
    var results = from u in users
                  where u.UserCode.Equals(userCode)
                  select u;
    return results.FirstOrDefault() != null;
}

您只需要设置GetUserSet以返回您的列表.这样的测试有一些重大问题:

>你没有测试真正的实现 – 如果EF嘲笑集是愚蠢的方法,因为一旦你这样做,你将linq-to-entity更改为linq-to-objects.这两个是完全不同的,linq到实体只是linq-to-objects的一小部分,你的单元测试可以通过linq-to-object传递,但你的代码在运行时会失败.
>一旦你使用这种方法,你不能使用Include,因为include取决于DbQuery / DbSet.再次,您需要集成测试才能使用它.
>这不会测试你的懒惰加载工作

更好的方法是从Validate方法删除您的LINQ查询 – 只需将它们称为对象的另一种虚拟方法即可.单元使用嘲弄的查询方法测试您的Validate方法,并使用集成测试来自行测试查询.

相关文章

迭代器模式(Iterator)迭代器模式(Iterator)[Cursor]意图...
高性能IO模型浅析服务器端编程经常需要构造高性能的IO模型,...
策略模式(Strategy)策略模式(Strategy)[Policy]意图:定...
访问者模式(Visitor)访问者模式(Visitor)意图:表示一个...
命令模式(Command)命令模式(Command)[Action/Transactio...
生成器模式(Builder)生成器模式(Builder)意图:将一个对...