zoukankan      html  css  js  c++  java
  • 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时就轻而易举的完成它的单元测试,后期开发效率与质量均得到保证。      

      编写完毕,借此抛砖引玉,希望得到您更好的意见,鲜花鸡蛋均欢迎。

  • 相关阅读:
    hdu 1086 You can Solve a Geometry Problem too 求n条直线交点的个数
    2019 上半年 南昌网络赛
    第十章 存储过程和函数
    第九章 Mysql函数
    第八章 Mysql运算符
    第七章 插入、更新与删除数据
    第六章 查询数据
    第五章 触发器
    第四章 视图
    第三章 索引
  • 原文地址:https://www.cnblogs.com/FreeDong/p/3233211.html
Copyright © 2011-2022 走看看