7

私はユニットテストにかなり慣れていません(私は実際に私たちが話すときにそれを研究しています)

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

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

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

これが私のクラスです:

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

これが私のテストの現在のコードです:

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);
            }
        }
    }
}
4

1 に答える 1

10

デコレータは、装飾されたオブジェクトに新しい動作を動的にアタッチします。それがデコレータの責任です。それはあなたがテストすべきものです。

それでは、次のコンポーネントのキャッシングデコレータを記述しましょう。

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

テストフィクスチャ(またはMSTestを使用している場合はTestClass)の作成

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

このコードをコンパイルするには、装飾されたコンポーネントを受け入れる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);
    }

良い。キャッシングコンポーネントは期待どおりに機能します。しかし、それは何もキャッシュしていません。そのためのライティングテスト。コンポーネントを1回だけ呼び出す必要があります。それ以降のすべての呼び出しは、キャッシュされた値を返す必要があります。

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

これで、動作が検証されたキャッシングデコレータができました。

于 2013-03-12T17:53:23.210 に答える