2013-03-12 2 views
5

私は単体テストにはまったく新しいです(私は実際に話しているように勉強しています)C#デコレータパターンに従ったクラスを適切に単体テストする方法は?

私の目標はもちろん、下のクラスの中のメソッドをテストできることです。

クラスは、入力がキャッシュ内にあるかどうかを単純にチェックします。入力がキャッシュにない場合は、入力の逆の形式を返します(実装はここにはありませんが、目的はちょうどテストすることです)。

基本的な目的は、if-elseがテストされていることを確認することです。

using System; 
using Microsoft.VisualStudio.TestTools.UnitTesting; 

namespace YouSource.Decorator.Tests 
{ 
    [TestClass] 
    public class CachingDecoratorTest 
    { 
     private IModifyBehavior behavior; 

     [TestInitialize] 
     public void Setup() 
     { 
      this.behavior = new StubModifyBehavior(new CachingDecorator()); 
     } 

     [TestCleanup] 
     public void Teardown() 
     { 
      this.behavior = null; 
     } 

     [TestMethod] 
     public void Apply_Cached_ReturnsReversedCachedValue() 
     { 
      string input = "randel"; 
      string reversed = "lednar"; 
      Assert.AreEqual(reversed, this.behavior.Apply(input)); 
     } 

     [TestMethod] 
     public void Apply_NotCached_ReturnsReversed() 
     { 
      string input = "not cached"; 
      string reversed = "reversed"; 
      Assert.AreEqual(reversed, this.behavior.Apply(input)); 
     } 

     public class StubModifyBehavior : IModifyBehavior 
     { 
      private IModifyBehavior behavior; 

      public StubModifyBehavior(IModifyBehavior behavior) 
      { 
       this.behavior = behavior; 
      } 

      public string Apply(string value) 
      { 

       //return this.behavior.Apply(value); 
      } 
     } 
    } 
} 

答えて

7

デコレータが動的に飾られているオブジェクトに新しい行動を添付:ここ

namespace YouSource.Decorator 
{ 
    using System; 
    using System.Collections.Generic; 
    using System.Linq; 
    using System.Text; 
    using System.Threading.Tasks; 

    /// <summary> 
    /// Caching Decorator 
    /// </summary> 
    public class CachingDecorator : IModifyBehavior 
    { 
     private IModifyBehavior behavior; 

     private static Dictionary<string, string> cache = 
      new Dictionary<string, string>(); 

     public string Apply(string value) 
     { 
      ////Key = original value, Value = Reversed 
      var result = string.Empty; 

      //cache.Add("randel", "lednar"); 
      if(cache.ContainsKey(value)) 
      { 

       result = cache[value]; 

      } 
      else 
      { 

       result = this.behavior.Apply(value);// = "reversed"; 
       cache.Add(value, result); 
      } 
      return result; 
     } 
    } 
} 

は私のテストの現在のコードです:

はここに私のクラスです。それはデコレータの責任です。それがあなたがテストすべきものです。このコードでは

[TestFixture] 
public class CachingComponentTests 
{ 
    private CachingComponent _cachingComponent; 
    private Mock<IComponent> _componentMock; 

    [SetUp] 
    public void Setup() 
    { 
     _componentMock = new Mock<IComponent>(); // using Moq in this sample 
     _cachingComponent = new CachingComponent(_componentMock.Object); 
    } 
} 

(あなたはMSTestをを使用している場合、またはTestClassを)あなたが作成する必要がコンパイルする

public interface IComponent 
{ 
    string DoSomething(string value); 
} 

作成テスト・フィクスチャ:

ので、以下のコンポーネントの書き込みキャッシュデコレータをすることができます装飾されたコンポーネントを受け入れるCachingComponentクラス。何かそんな感じです(少しスピードアップします):

public class CachingComponent : IComponent 
{ 
    private IComponent _component; 

    public CachingComponent(IComponent component) 
    {    
     _component = component; 
    } 

    public string DoSomething(string value) 
    { 
     throw new NotImplementedException(); 
    } 
} 

次に、デコレータの予想される動作を定義しましょう。

[Test] 
public void ShouldCallComponentWhenCalledFirstTime() 
{ 
    _componentMock.Setup(c => c.DoSomething("foo")).Returns("bar"); 

    Assert.That(_cachingComponent.DoSomething("foo"), Is.EqualTo("bar")); 
    _componentMock.Verify(); 
} 

をそして、それは、このようにメソッドがまだ実装されていません失敗します。それは、いくつかのパラメータを持つ最初の呼び出しがある場合は、コンポーネントの呼び出しを渡す必要があります。最初の実装(よく、最も簡単な実装はnullを返しますが、ここではほとんど動きません)。

ニース。私たちのキャッシングコンポーネントは期待通りに動作します。しかし、それは何もキャッシュしていません。そのためのテストを書く。コンポーネントを一度呼び出す必要があります。

[Test] 
public void ShouldReturnCachedValueWhenCalledMoreThanOnce() 
{ 
    _componentMock.Setup(c => c.DoSomething("foo")).Returns("bar"); 

    Assert.That(_cachingComponent.DoSomething("foo"), Is.EqualTo("bar")); 
    Assert.That(_cachingComponent.DoSomething("foo"), Is.EqualTo("bar")); 
    _componentMock.Verify(c => c.DoSomething("foo"), Times.Once()); 
} 

と実装:すべての更なる呼び出しは、キャッシュされた値を返す必要があります

public class CachingComponent : IComponent 
{ 
    private Dictionary<string, string> _cache = new Dictionary<string, string>(); 
    private IComponent _component; 

    public CachingComponent(IComponent component) 
    {    
     _component = component; 
    } 

    public string DoSomething(string value) 
    { 
     if (!_cache.ContainsKey(value))    
      _cache.Add(value, _component.DoSomething(value));    

     return _cache[value]; 
    } 
} 

は今、あなたは検証動作でデコレータをキャッシュしています。

関連する問題