2011-11-02 56 views
14

我已经看了很多别人的QA关于这个话题,我仍然无法找到解决我的问题,所以我决定揭露我的案子。Moq.Mock <表达式<Func<T,bool> >>() - 如何设置表达式为模拟使用起订量

我有这个接口

public interface IRepository<T> where T : class, IEntity 
{ 
    IQueryable<T> Find(Expression<Func<T, bool>> predicate); 
    T FindIncluding(int id, params Expression<Func<T, object>>[] includeProperties); 
} 

这是包含模拟,我想该方法的基本结构,建立

public PeopleController CreatePeopleController() 
{ 
    var mockUnitofWork = new Mock<IUnitOfWork>(); 
    var mockPeopleRepository = new Mock<IRepository<Person>>(); 

    mockPeopleRepository.Setup(r=>r.Find().Returns(new Person(){}); 
    mockUnitofWork.Setup(p => p.People).Returns(mockPeopleRepository.Object); 
    return new PeopleController(mockUnitofWork.Object); 
} 

我一直在试图建立素使用这样:

public PeopleController CreatePeopleController() 
{ 
    var mockUnitofWork = new Mock<IUnitOfWork>(); 
    var mockPeopleRepository = new Mock<IRepository<Person>>(); 

    mockPeopleRepository.Setup(r=>r.Find(It.isAny<Expression<Func<Person,bool>>>()).Single()).Returns(new Person(){}); 
    mockUnitofWork.Setup(p => p.People).Returns(mockPeopleRepository.Object); 
    return new PeopleController(mockUnitofWork.Object); 
} 

但系统总是抛出相同的异常“System.NotSup portedException:表达式引用不属于嘲笑对象的方法......“

另外我想补充一点,我使用MSTest的起订量和

我知道,设置一个模拟使用表达式不方便,不推荐,但对我来说非常重要,因为“发现”是,我在我的应用程序使用了很多方法

回答

19

的问题是,你要设置单()扩展方法的一部分你的嘲笑。设置调用需要你的方法的结果 - 而不是你的方法的结果随后应用一些扩展方法。我想试试这个:

[TestMethod] 
    public void MyTestMethod() 
    { 
     var myMock = new Mock<IRepository<Person>>(); 
     myMock.Setup(r => r.Find(It.IsAny<Expression<Func<Person, bool>>>())).Returns(new List<Person>() { new Person() }.AsQueryable()); 

     Assert.IsTrue(true); 
    } 

在这里,你只是磕碰与设置您的find()方法,做所有的其他的东西,在返回()子句。我一般会建议这种方法。安装程序应准确反映你的嘲笑项目,你可以做一堆黑魔法的收益()(或抛出()或其他)调用得到它做你想要的。

(当我跑VS的代码,它通过了,所以它不是抛出一个异常)

+0

埃里克只实现您的解决方案及其工作..谢谢您帮帮我!!! :) – gustavotroconis

+0

很高兴帮助。 :)如果 –

+0

@gustavotroconis这个答案解决您的问题,您可以点击旁边的复选标记接受它。当你问更多的问题,“接受%”将出现你的头像下方,以及较高%鼓励其他人回答您的问题。 –

4

使用起订量的It.IsAny<>没有.CallBack强迫你写,并不包括在你的测试代码。相反,它允许任何查询/表达式都可以通过,从单元测试的角度来看,你的模拟基本上是无用的。

解决办法:要么你需要使用一个回调来测试表达或需要约束的模拟更好。无论哪种方式都是混乱和困难的。我已经处理了这个问题,因为我一直在练习TDD。我终于把一个帮手班放在一起,让这个表达更多,更少杂乱。这里的最终结果(适用于你的例子):

mockPeopleRepository 
    .Setup(x => x.Find(ThatHas.AnExpressionFor<Person>() 
    .ThatMatches(correctPerson) 
    .And().ThatDoesNotMatch(deletedPerson) 
    .Build())) 
    .Returns(_expectedListOfPeople); 

下面是谈论它,并给出了源代码的博客文章:http://awkwardcoder.com/2013/04/24/constraining-mocks-with-expression-arguments/

相关问题