2008-08-07 12 views
5

私の最新の災害は、嘲笑に悩まされています。私は実際にIEnumerable<T>というモックオブジェクトの中に結果をプッシュする必要があります。ここで IEnumerable <T>を正しく模擬していますか?

はサンプルです(のみ IEnumerable<T>のデモではなく、実際に良好な相互作用ベースのテスト!):私は次のような理由のために働くためにそれを得た方法

using System; 
using System.Collections.Generic; 
using Rhino.Mocks; 
using MbUnit.Framework; 

[TestFixture] 
public class ZooTest 
{ 
    [Test] 
    public void ZooCagesAnimals() 
    { 
     MockRepository mockery = new MockRepository(); 

     IZoo zoo = new Zoo(); 

     // This is the part that feels wrong to create. 
     IList<IAnimal> mockResults = mockery.DynamicMock<IList<IAnimal>>(); 
     IAnimal mockLion = mockery.DynamicMock<IAnimal>(); 
     IAnimal mockRhino = mockery.DynamicMock<IAnimal>(); 

     using (mockery.Record()) 
     { 
      Expect.Call(zoo.Animals) 
       .Return(mockResults) 
       .Repeat.Once(); 
     } 

     using (mockery.Playback()) 
     { 
      zoo.CageThe(mockLion); 
      zoo.CageThe(mockRhino); 

      Assert.AreEqual(mockResults, new List<IAnimal>(zoo.Animals)); 
     }  
    } 
} 


public class Zoo : IZoo 
{ 
    private IList<IAnimal> animals = new List<IAnimal>(); 

    public void CageThe(IAnimal animal) 
    { 
     animals.Add(animal); 
    } 

    public IEnumerable<IAnimal> Animals 
    { 
     get 
     { 
      foreach(IAnimal animal in animals) 
      { 
       yield return animal; 
      } 
     } 
    } 
} 

public interface IAnimal 
{ 
} 

public interface IZoo 
{ 
    IEnumerable<IAnimal> Animals { get;} 
    void CageThe(IAnimal animal); 
} 

私は好きではない:

  • IEnumerable<IAnimal>の結果を消費するとIList<IAnimal>になります。これはヒープにチェックするための結果です。
  • 結果の設定 - 私も同様に理解しています。私の主なポイントは、Zoo.AnimalsIEnumerable<IAnimal>を返していることをテストすること、さらには、yield returnを使用していることをテストすることです。

これをより簡単にするための提案はありますか?

編集:IEnumerable<T>と私が使用しているものとのやりとりをテストする最適な方法を判断しようとしています。私はそのZooIEnumerable<IAnimal>として公開し、むしろ、動物を保持することができるZooをテストするつもりはないよ、とyield returnことにも慣れてきています。

+1

振り返ってみると、これは** TERRIBLE **の質問です。閉じる投票しようとする –

答えて

4

の実装をテストしているのであれば、なぜあなたは最初にそれを模擬しようとしていますか?なぜCageThe(IAnimal)だけでなく、AnimalsにそのIAnimalが含まれていることを確認するのはなぜですか?

私はあなたがまだ具体的な動物を持っていないように見えるが、スタブを作ってはいけないと思うので、あなたはIAnimalsを嘲笑している。それらをリストに入れることとは別に?

編集:

[TestFixture] 
public class ZooTest 
{ 
    [Test] 
    public void ZooCagesAnimals() 
    { 
     MockRepository mockery = new MockRepository(); 

     IAnimal mockLion = mockery.Stub<IAnimal>(); 
     IAnimal mockRhino = mockery.Stub<IAnimal>(); 

     IZoo zoo = new Zoo(); 

     zoo.CageThe(mockLion); 
     zoo.CageThe(mockRhino); 

     List<IAnimal> animals = new List<IAnimal>(zoo.Animals); 
     Assert.IsTrue(animals.Contains(mockLion)); 
     Assert.IsTrue(animals.Contains(mockRhino)); 
    } 
} 
3

私はかなりあなたがに期待するのモック期待を設定する方法を見ていない:およそこれらの線に沿って何か(テストしていませんが、あなたの犬などを食べることができる、コンパイルされない場合があります)モックではないオブジェクトから始まります。また、コンパイラがイテレータを生成したときに実際に起こることではないIListを返すことを期待しています。

あなたは、具体的イテレータをテストしたい場合は、おそらく

Assert.IsNotNull(zoo.Animals); 

そして列挙子は実際にあなたが動物園に追加されたすべてのものの上に列挙していることを確認する必要があります。それは私がそこで行っていたものです。 :)

私は降伏リターンは、コンパイラが生成してIEnumerableのためだけ糖衣構文であるため、歩留まりのリターンは、呼び出されている場合、それはテストすることも可能ですかはわかりません。例えば、

zoo.Animals.GetEnumerator(); 

を呼び出すと、列挙子に書いたコードは実行されません。最初に起こるのはIEnumeratorへの最初の呼び出しです。MoveNext();

具体的な動物園とその動物園に含まれるIEnumerableとのやりとりをテストしようとしている場合は、動物園でIEnumerableフィールドを作成し、具体的なIEnumerableを実装する代わりにそのフィールドに模擬IEnumerableを注入する必要があります動物園で直接。

私はこれが何らかの援助であることを望みます。

関連する問題