2011-03-02 12 views
3

FakeItEasyで偽物を作成して、連続呼び出しで異なる戻り値を許可するにはどうすればできますか?FakeItEasyで列挙子を偽る

var enumerator = A.Fake<IDictionaryEnumerator>(); 
A.CallTo(() => enumerator.MoveNext()).Returns(true); //Expected value for first call 
A.CallTo(() => enumerator.Key).Returns("key1"); 
A.CallTo(() => enumerator.Value).Returns("value1"); 
A.CallTo(() => enumerator.MoveNext()).Returns(false); //Expected value for second call 

Assert.IsTrue(enumerator.MoveNext()); //Fails 
Assert.IsFalse(enumerator.MoveNext()); 

アサーションが最初のものを上書きしますので、それMoveNextメソッドの最後のセットアップに失敗します:これは私が行うことができるようにしたいものの一例です。

FakeItEasyで私がしたいことはできますか?


は、元の質問の例を明確化し、以下の実施例を提供

[編集]。

パトリックの答えに基づいて、このコードはあなたが偽をセットアップする方法を示しています。そのトリックはすべての設定を逆にしてOnce()を使用することです。

var enumerator = A.Fake<IDictionaryEnumerator>(); 
A.CallTo(() => enumerator.MoveNext()).Returns(false).Once(); 
A.CallTo(() => enumerator.MoveNext()).Returns(true).NumberOfTimes(2); 
A.CallTo(() => enumerator.Key).Returns("key2").Once(); 
A.CallTo(() => enumerator.Value).Returns("value2").Once(); 
A.CallTo(() => enumerator.Key).Returns("key1").Once(); 
A.CallTo(() => enumerator.Value).Returns("value1").Once(); 

while(enumerator.MoveNext()) 
{ 
    Debug.WriteLine(enumerator.Key + ": "+ enumerator.Value);    
} 

これを印刷します:

key1: value1 
key2: value2 

答えて

6

私はあなたが何を意味するか理解していることを全くわからないんだけど、あなたが与えたコードは常に失敗します。しかし、あなたがそれが真実を返すことを意味する場合は、時間と呼ばれることができます。そのうちの二つがある私は考えることができるさまざまな方法のいくつかあります。

A.CallTo(() => enumerator.MoveNext()).ReturnsNextFromSequence(false, true); 

他の方法は次のとおりです。

A.CallTo(() => enumerator.MoveNext()).Returns(true); 
A.CallTo(() => enumerator.MoveNext()).Returns(false).Once(); 

編集:秒で

私は推測しても私はあなたの質問をよりよく理解しています。何をしたいのですか?MoveNextは最初にtrueを返し、2回目にfalseを返します。その場合は、上記の例の値の順序を変更するだけです。

FakeItEasyはレコード/再生モデルを使用せず、最新の設定ルールが以前に指定されたルールよりも優先されるという点で正しいです。そのため、一度有効にするには、最新の設定でrepeat - ".Once()"を指定する必要があります。

最新のものが優先される理由は数多くありますが、最も重要なものの1つは、フィクスチャの設定でデフォルトの戻り値を設定し、その値を上書きしていくつかのテストで特定の値を返し、これは、レコード/再生モデルを使用する場合は不可能です。

+0

はい、そうです。私はレコード/リプレイモデルの後だった。 FakeItEasyには意味がありません。私は質問を編集し、2つのMoveNextに値を与える実例を含めます。助けてくれてありがとう。 – hcanber

0

パトリックの答えに基づくOPの例はうまくいきますが、シーケンスが大きくなると面倒です。その答えを補足するために、擬似/模擬の例では、多くの場合、自分自身を配置するための一連の直線コードが表示されていますが、実際にはコマンドに完全なプログラミング言語の力があります。条件、ループ、さらには手続き。

public static void AFakeDictionaryEnumeratorReturns(
         IDictionaryEnumerator enumerator, params object[] pairs) 
{ 
    if (0 != pairs.Length % 2) 
     throw new ArgumentException("pairs must have even number of elements", "pairs"); 

    int n = pairs.Length/2; 

    A.CallTo(() => enumerator.MoveNext()).Returns(false).Once(); 
    A.CallTo(() => enumerator.MoveNext()).Returns(true).NumberOfTimes(n); 

    for (int i = pairs.Length; i > 0; i -= 2) 
    { 
     A.CallTo(() => enumerator.Key).Returns(pairs[i - 2]).Once(); 
     A.CallTo(() => enumerator.Value).Returns(pairs[i - 1]).Once(); 
    } 
} 

を、現在の試験は次のようになります:

だから次の点を考慮してペアで

var enumerator = A.Fake<IDictionaryEnumerator>(); 
AFakeDictionaryEnumeratorReturns(enumerator, 
           "key1", "value1", "key2", "value2", "key3", "value3"); 

var keys = new List<object>(); 
var values = new List<object>(); 
while (enumerator.MoveNext()) 
{ 
    keys.Add(enumerator.Key); 
    values.Add(enumerator.Value); 
} 

Assert.Equal(new List<object> { "key1", "key2", "key3" }, keys); 
Assert.Equal(new List<object> { "value1", "value2", "value3" }, values); 

IDictionaryEnumerator取引をするので、この例では、それができるほど明確に有益ではありません。標準IEnumerator<T>の場合、単一の静的汎用メソッドは、異なる列挙子の束全体に役立ちます。)