2013-03-12 3 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을 반환하지만 여기서 조금 더 빠르게 움직이고 있습니다.) :

public string DoSomething(string value) 
    { 
     return _component.DoSomething(value); 
    } 

Nice. 캐싱 구성 요소가 예상대로 작동합니다. 그러나 그것은 아무것도 캐싱하지 않습니다. 그것을위한 시험을 쓰고. 구성 요소를 한 번만 호출해야합니다.

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]; 
    } 
} 

지금 당신이 검증 된 행동 캐싱 장식이 있습니다

[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()); 
} 

및 구현 : 모든 추가 호출이 캐시 된 값을 반환해야합니다.

관련 문제