12

次のテストケースは、サイのモックで失敗します。

[TestFixture] 
    public class EnumeratorTest 
    { 
        [Test] 
        public void Should_be_able_to_use_enumerator_more_than_once() 
        { 
            var numbers = MockRepository.GenerateStub<INumbers>(); 
            numbers.Stub(x => x.GetEnumerator()).Return(new List<int> 
{ 1, 2, 3 }.GetEnumerator()); 
            var sut = new ObjectThatUsesEnumerator(); 
            var correctResult = sut.DoSomethingOverEnumerator2Times 
(numbers); 
            Assert.IsTrue(correctResult); 
        } 
    } 
    public class ObjectThatUsesEnumerator 
    { 
        public bool DoSomethingOverEnumerator2Times(INumbers numbers) 
        { 
            int sum1 = numbers.Sum(); // returns 6 
            int sum2 = numbers.Sum(); // returns 0 =[ 
            return sum1 + sum2 == sum1 * 2; 
        } 
    } 
    public interface INumbers : IEnumerable<int> { } 

このテストケースには非常に微妙な点があると思います。RhinoMocksのスタブが実際にどのように機能するかを考えていないのは私からだと思います。通常、IEnumerableを列挙するときは、新しいIEnumeratorから始めます。上記の例では、2回目にsumを呼び出すときに同じ列挙子を再利用できるように見えます。列挙子がすでにシーケンスの最後にある場合は、Sum()への2回目の呼び出しが返される理由を説明します。 0.この場合、GetEnumerator()を希望どおりに動作するようにモックアウトするにはどうすればよいですか(たとえば、新しい列挙子または同じ列挙子が位置0にリセットされます)。

2番目の.Sum()呼び出しが実際に0ではなく6を返すように、上記のテストケースをどのように変更しますか?

4

3 に答える 3

13

WhenCalled() API を使用すると、戻り値を動的に解決できます。

テスト ケースを次のように変更すると、テストに合格できます。

numbers.Stub(x => x.GetEnumerator())
                     .Return(null)
                     .WhenCalled(x => x.ReturnValue = 
                                    new List<int> { 1, 2, 3 }.GetEnumerator()
                                 );

そのため、同じ列挙子を返す代わりに、スタブ化された動作は常に新しい列挙子を返します。

于 2008-12-30T17:40:58.923 に答える
3

ステートメント

numbers.Stub(x => x.GetEnumerator()).Return(new List<int> { 1, 2, 3 }.GetEnumerator());

と同じです

var enumerator = new List<int> { 1, 2, 3 }.GetEnumerator();
numbers.Stub(x => x.GetEnumerator()).Return(enumerator);

テストでは、RhinoMocksに同じIEnumerator<int>インスタンスenumeratorを2回与えるように指示しています。それはあなたが意図したものではありません。の単一のインスタンスはIEnumerator<int>、2つの列挙ではなく、1つの列挙にのみ有効です(Reset()通常はサポートされていません)。Rhino Mocksがの2つの異なるインスタンスを提供することを意図しIEnumerator<int>ていたので、他のGetEnumerator<int>()関数への呼び出しと同じように、それらを別々に合計できます。

于 2008-12-24T20:15:40.257 に答える
0

免責事項: 私は Typemock で働いています

これを行うためにRhinoを使用できるかどうかはわかりませんが、まさに探しているものを備えたAAA APIでIsolatorを使用できます-

[Test] 
public void Should_be_able_to_use_enumerator_more_than_once() 
{
   var numbers = Isolate.Fake.Instance<INumbers>();
   Isolate.WhenCalled(() => numbers).WillReturnCollectionValuesOf(new List<int>{ 1, 2, 3 });
   var sut = new ObjectThatUsesEnumerator(); 
   var correctResult = sut.DoSomethingOverEnumerator2Times(numbers); 
   Assert.IsTrue(correctResult); 
}

詳細については、開発者ガイドの「コレクションの管理」を参照してください。

于 2008-12-24T14:44:15.370 に答える