2011-11-02 20 views
14

私はこのトピックに関する多くの他のQAを読んできましたが、私の問題の解決策はまだ見つかりません。私のケースを公開することに決めました。Moq.Mock <式<Func<T,bool> >> - Moqを使用してモックに式を設定する方法

私は、このインターフェイス

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:Expressionが嘲笑オブジェクトに属していないメソッドを参照する.... "

また、私は私がセットアップモック使って表現ではないことを知っている私はMSTestをし、部品番号に

を使用していますことを追加したいと思います簡単ではありませんが、私にとっては非常に重要です。なぜなら、「Find」は私のアプリでたくさん使う方法なのですから。

答えて

19

問題は、あなたがSingle()拡張メソッドをあなたの嘲笑セットアップコールにはメソッドの結果が必要です。メソッドの結果ではなく、後で拡張メソッドが適用されます。あなただけのセットアップを使用して検索()メソッドをスタブ、および戻り値()句で他のもののすべてをやっている、ここで

[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); 
    } 

:私はこれを試してみました。私はそのアプローチを一般的に提案します。セットアップではあなたの模擬アイテムを正確に反映させる必要があります。あなたが望むことをやり遂げるためには、Return()(またはThrows()など)の呼び出しに対して黒い魔法の束を使うことができます。

(私はVSでそのコードを実行したとき、それは渡されたので、それは例外を投げていなかった)あなたが試験でカバーされていないコードを書くこと.CallBack力なしに部品番号のIt.IsAny<>を使用して

+0

エリックちょうどあなたのソリューションとその作業を実施。..あなたのためのおかげで助けて!!! :) – gustavotroconis

+0

喜んで助けた。 :) –

+0

@ gustavotroconisこの回答があなたの問題を解決した場合は、その横にあるチェックマークをクリックして受け入れることができます。より多くの質問をすると、あなたのアバターの下に「受け入れ率」が表示され、他の人があなたの質問に答えるよう促す%が高くなります。 –

4

を。代わりに、すべてのクエリ/式を通過させることができるため、モックを基本的に単体テストの観点からは役に立たなくすることができます。

解決策:式をテストするためにコールバックを使用するか、モックをよりよく制約する必要があります。どちらの方法も面倒で難しい。私は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/

関連する問題