2011-11-02 55 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/

相關問題