2011-09-27 4 views
2

FakeIteasy CallToアサーションで式ツリーを引数制約として使用できますか?式ツリーを引数制約として使用

:私は心の中でこのような何かをやってユニットテストを持っている

Flight flight = repository.Single(f => f.ID == id); 

:そうのようなコードで呼び出されている

interface IRepository<TEntity> 
{ 
    TEntity Single(Expression<Func<TEntity, bool>> predicate); 

:次のシグネチャを持つインタフェース上の方法を考える

Expression<Func<Flight, bool>> myExpression = flight => flight.ID == 1; 

A.CallTo(() => repository.Single(
        A<Expression<Func<Flight, bool>>>.That.Matches(myExpression))) 
        .Returns(new Flight()); 

しかし、これは警告を生成します:タイプargumenを指定してみてください明示的にです。

現在、Ignoredプロパティは理想的ではありません。

答えて

1

おかげでパトリックは、発現を調べる

は私が行うために必要な正確に何をした、すなわち式(F => f.ID == ID)を解析し、取得するために==の右側を実行しますランタイム値。コードで

これは次のようになります。私は、同じ目的を達成するために、よりエレガントな方法がなければならないことを考えて助けることはできませんしかし

A.CallTo(() => flightRepository.Single(A<Expression<Func<Flight, bool>>>.That 
       .Matches(exp => Expression.Lambda<Func<int>>(((BinaryExpression)exp.Body).Right).Compile().Invoke() == 1))) 
       .Returns(new Flight()); 

。私は別の日のためにそれを残すでしょう。

おかげで再び、引数として式を主張しようとしたときに マイケル・マクドウェル

+0

私はよりエレガントな解決策はIRepository よりも別の抽象化に依存すると考えていますが、これは例えばIFlightRepositoryかもしれません(しかし他の魅力的な選択肢もあります)。 IFlightRepositoryがメソッド "GetFlightById"を公開している場合は、これをテストするのに問題はありません。一方、航空倉庫の実装は、IRepository に非常によく頼ることができます。これは金属に非常に近く、ユニットテストは必要ありませんが、統合テストでカバーする必要があります。しかしこれは私の個人的な意見です。 –

+0

確かに、definitlayには、EntLibのデータアクセスコードを抽象化する別のレイヤーが必要です。私は現在、さまざまな解決策で苦労しています。どんな指針も大変ありがとうございます。 –

2

「一致」-methodはラムダを受け取りますが、式に渡そうとしています。あなたは "マッチ"で何を言おうとしていますか?平等にマッチしていますか?その場合は、次のように書いてください:

A.CallTo(()=> repository.Single(myExpression))戻り値(新しいFlight());

表現を他のものに拘束したい場合は、タイプ「Func<Expression<Func<Flight, bool>>, bool>」の述語を「一致」メソッドに渡す必要があります。

+0

私はこれを最初に試しましたが、呼び出しは決して傍受されず、偽の厳格性が確認されます。試行された試合(a => a == myExpression)も傍受されません。 –

+0

あなたは何をしたいのですか?式はどのようにしてテストからリポジトリに渡されますか?ほとんどの場合(すべてではない)ほとんどの場合、等式の式を一致させるのはちょっと奇妙に思えます。ほとんどの場合、渡された式が等価でないかどうかを判断するテストになります。あなたは、呼び出しが全く傍受されていないと言います。 –

+0

こんにちは@Patric、偽のstrictがExpectationException(未構成の偽の呼び出し)をスローするようにします。私が傍受したいリポジトリの呼び出しは、このrepository.Single(f => f.ID == id)のようになり、変数idが1のときに傍受したい。 –

0

私は同じ問題を抱えていたが、私は部品番号を使用していました。 Moq Expect On IRepository Passing Expression

それは基本的にあなたが表現上のtoString()を行うことができますと言うと:解決策は、私は同様の質問にこの回答への信用のほとんどを与える

...あなたにもかかわらずのために働く必要がありますそれらを比較する。それは一種のハッキーですが、一つの欠点しかありません。 ラムダ式の変数名は一致しなければなりません。ここで

は一例です...

[Test] 
    public void TestWhichComparesExpressions() 
    { 
     // setup 
     _mockRepository.Setup(x => x.GetByFilter(MatchQuery())).Returns(new List<Record>()); 

     // execute 
     var records = _service.GetRecordsByFilter(); 

     // assert 
     Assert.IsNotNull(records); 
     Assert.AreEqual(0, records.Count()); 
    } 

    private static Expression<Func<DomainRecord, bool>> MatchQuery() 
    { 
     return MatchExpression(ServiceClass.QueryForTheRecords); // constant 
    } 

    // https://stackoverflow.com/questions/288413/moq-expect-on-irepository-passing-expression/1120836#1120836 
    private static Expression<Func<DomainRecord, bool>> MatchExpression(Expression<Func<DomainRecord, bool>> expression) 
    { 
     return It.Is<Expression<Func<DomainRecord, bool>>>(e => e.ToString() == expression.ToString()); 
    } 

私は誰かが、ラムダ式の年代を変更した場合、それはテストで同じになる保証され、それを使用するクラスの定数への発現を置くことにしました変数名。

関連する問題