VS2012 Unit Test —— 我對接口進行單元測試使用的技巧


 【題外話】

  對單元測試不熟悉的童鞋可參照我之前寫過的兩篇博文:

在Visual Studio 2012使用單元測試》、

VS2012 單元測試之泛型類(Generics Unit Test)》。
  

  以下Demo將使用我已寫好的一些關於單元測試的類庫(已放至 https://idletest.codeplex.com/ 

,其用了大量的匿名方法,同樣不熟悉的可參照我上一篇博文《委托的N種寫法,你喜歡哪種?

 

【進入正題】

   與其說對接口測試還不如說針對抽象測試,也是我個人比較喜歡的編碼步驟:編寫接口(面向抽象)=>單元測試=>實現。

  OK here we go...

  首先假設有如下接口(這也是從我的代碼中提取出來的)

    public interface ITextFormatter
    {
        /// <summary>
        /// 根據指定格式字符串獲取對象
        /// </summary>
        T GetObject<T>(string formatString);

        /// <summary>
        /// 將對象轉化為指定格式字符串
        /// </summary>
        string GetString(object obj);
    }

 

  那么接下來我要做的並不是馬上去實現它,而是測試先行,我將編寫如下測試代碼

    public abstract class BaseFormatterTest
    {
        protected abstract ITextFormatter formatter
        {
            get;
        }
        
        /// <summary>
        ///GetObject 的測試
        ///</summary>
        public void GetObjectTestHelper<T>()
        {
            AssertCommon.AssertIsNull<string, T>(TestCommon.GetEmptyStrings(), true, (string strTemp) => {
                return formatter.GetObject<T>(strTemp);
            });

            EntityParameter ep = new EntityParameter(123);
            string str = formatter.GetString(ep);
            EntityParameter actual = formatter.GetObject<EntityParameter>(str);
            Assert.IsNotNull(actual);
            Assert.AreEqual<int>(123, actual.Data);
        }

        public virtual void GetObjectTest()
        {            
            GetObjectTestHelper<GenericParameterHelper>();
        }

        /// <summary>
        ///GetString 的測試
        ///</summary>
        public virtual void GetStringTest()
        {
            AssertCommon.AssertEmpty<string>(formatter.GetString(null));

            AssertCommon.AssertEmpty<string>(formatter.GetString(new object()), false);

            string actual = formatter.GetString(new EntityParameter(12));
            AssertCommon.AssertEmpty<string>(actual, false);
            EntityParameter entity = formatter.GetObject<EntityParameter>(actual);
            Assert.AreEqual<int>(12, entity.Data);
        }
針對接口測試抽象基類

值得注意的是以上方法中包含了一個叫做AssertCommon類,這個是我自己定義的,源碼在 https://idletest.codeplex.com/。

  我現在通過Xml序列化實現字符串與對象的相互轉化,所以我繼承這個基類來編寫具體的測試,當然此時的測試代碼就很簡單了。

    /// <summary>
    ///這是 ITextFormatterTest 的測試類,旨在
    ///包含所有 ITextFormatterTest 單元測試
    ///</summary>
    [TestClass()]
    public class XmlFormatterTest : BaseFormatterTest
    {
        [TestMethod()]
        public override void GetObjectTest()
        {
            base.GetObjectTest();
        }

        /// <summary>
        ///GetString 的測試
        ///</summary>
        [TestMethod]
        public override void GetStringTest()
        {
            base.GetStringTest();
        }

        protected override ITextFormatter formatter
        {
            get { return new XmlFormatter(); }
        }
    }

  完成測試編碼后開始實現具體代碼,我這里將創建一個抽象基類和一個子類去實現需要的功能

    public abstract class BaseFormatter
    {
        private Encoding encoding;
        public Encoding Encoding
        {
            get { return this.encoding; }
        }

        public BaseFormatter(Encoding encoding)
        {
            this.encoding = encoding;
        }
    }
    public class XmlFormatter : BaseFormatter, ITextFormatter
    {
        public XmlFormatter() : base(Encoding.Default) { }

        public XmlFormatter(Encoding encoding) : base(encoding) { }

        /// <summary>
        /// 將對象序列化為XML格式字符串
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public string GetString(object obj)
        {
            string result = string.Empty;
            if (obj ==null)
            {
                return result;
            }

            XmlSerializer serializer =new XmlSerializer(obj.GetType());            
            using (MemoryStream stream =new MemoryStream())
            {
                serializer.Serialize(stream, obj);
                byte[] buffer = stream.ToArray();
                result = this.Encoding.GetString(buffer);
                stream.Close();
            }

            return result;
        }

        ///<summary>
        /// 將XML格式字符串轉化為對象
        ///</summary>
        public T GetObject<T>(string xmlString)
        {
            T obj = default(T);
            if (string.IsNullOrEmpty(xmlString))
            {
                return obj;
            }

            XmlSerializer serializer =new XmlSerializer(typeof(T));
            using (MemoryStream stream = new MemoryStream(this.Encoding.GetBytes(xmlString)))
            {
                obj = (T)serializer.Deserialize(stream);
                stream.Close();
            }

            return obj;
        }
    }

整個過程就這樣子,當然中間肯定運行多次測試來即時修正編碼過程中的錯誤。篇幅有限,我在這里並沒有編寫構造函數的測試方法。

   

【后話】

  如此一來以后再添加對接口的更多實現時,保證了不再需要編寫大量重復的測試代碼,例如再增加類JsonFormatter時就輕而易舉的完成它的單元測試,后期開發效率與質量均得到保證。      

  編寫完畢,借此拋磚引玉,希望得到您更好的意見,鮮花雞蛋均歡迎。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM