zoukankan      html  css  js  c++  java
  • 从vs2010的UnitTestFramework类库提取私有方法反射调用的方法

    背景

    年龄大点的程序员都知道在vs2010中创建单元测试非常的简单,鼠标定位在方法名字,右键创建单元测试,就会创建一个测试方法,即使是在私有方法上也可以创建测试方法。

    VS2010以后就没这么简单了,微软默认取消了这种快捷方式,安装  Unit Test Generator 插件也只能在公有方法上创建单元测试。为了方便的测试私有方法,我们需要一种反射调用私有成员的方法。这种现成的方法可以在网上找到不少,我这里是讲述如何从VS2010

    的UnitTestFramework类库提取反射调用私有成员的方法。

    VS2010私有方法单元测试分析

    在vs2010里新建个测试类:

      public class Class1
        {
            private string GetName(string name, int age)
            {
                return name + age;
            }
        }
    Class1

    创建单元测试

           /// <summary>
            ///GetName 的测试
            ///</summary>
            [TestMethod()]
            [DeploymentItem("ClassLibrary1.dll")]
            public void GetNameTest()
            {
                Class1_Accessor target = new Class1_Accessor(); // TODO: 初始化为适当的值
                string name = string.Empty; // TODO: 初始化为适当的值
                int age = 0; // TODO: 初始化为适当的值
                string expected = string.Empty; // TODO: 初始化为适当的值
                string actual;
                actual = target.GetName(name, age);
                Assert.AreEqual(expected, actual);
                Assert.Inconclusive("验证此测试方法的正确性。");
            }
    Class1 Test

    有这么一行    [DeploymentItem("ClassLibrary1.dll")],多了个  Class1_Accessor

    使用ILSpy打开ClassLibrary1.dll看看

    可以看出Class1_Accessor : BaseShadow ,实例化时调用了基类的构造方法,实例化一个privateObject并赋给了m_privateObject ,GetName方法就是调用了m_privateObject 的invoke获取返回值。

    protected BaseShadow(PrivateObject privateTarget)
    {
        this.m_privateObject = privateTarget;
    }

    沿着 BaseShadow ->PrivateObject->PrivateType->RuntimeTypeHelper->Helper的顺序把相关的代码都保存下来,文章最后提供下载。

    其中用到FrameworkMessages 的都是错误信息相关的,用到了资源文件。这里没有照搬而是把用到的几个信息敲了一遍,如下:

     class FrameworkMessages
        {
            public static string PrivateAccessorMemberNotFound(string name)
            {
                return string.Format("The member specified ({0}) could not be found.You might need to regenerate your private accesscor the member may be private and defined on a base class." +
                             "If the latter is true,you need to pass the type that defines the member  into PrivateObject's constructor", name);
            }
    
            public static string AccessStringInvalidSyntax
            {
                get { return "Access string has invalid syntax."; }
            }
      
    
            public static string PrivateAccessorConstructorNotFound
            {
                get { return "The constructor with the specified signature could not be found.You might need to regenerate your private accesscor the member may be private and defined on a base class." +
                             "If the latter is true,you need to pass the type that defines the member  into PrivateObject's constructor"; }
            }
    
        }
    FrameworkMessages

    用到的方法找齐了,写个测试用例,首先定义一个需要访问的类

        public class DemoClass
        {
            public string Name { get; set; }
            public int Age { get; set; }
            public DemoClass():this("zeroes",100)
            {
            }
    
            public DemoClass(string name, int age)
            {
                this.Name = name;
                this.Age = age;
            }
    
            private string PrivateMethod(DateTime time)
            {
                return "姓名:{0} 年龄:{1} 时间:{2}".FormatWith(this.Name, this.Age, time.ToString("yyyy"));
            }
        }
    DemoClass

    然后封装一个私有反射的帮助类

    /// <summary>
        /// 调用方法单元测试管理类
        /// </summary>
        public static class PrivateUnitTestUtil
        {
    
            /// <summary>
            /// 调用私有方法
            /// </summary>
            /// <param name="t">要访问的类类型</param>
            /// <param name="methodName">方法名字</param>
            /// <param name="paras">参数</param>
            /// <returns></returns>
            public static object InvokeMethod(Type t,  string methodName, params object[] paras)
            {
                var privateObject = new PrivateObject(t);
                return privateObject.Invoke(methodName, paras);
            }
    
            /// <summary>
            /// 调用私有方法
            /// </summary>
            /// <param name="instance">要访问的类实例</param>
            /// <param name="methodName">方法名字</param>
            /// <param name="paras">参数</param>
            /// <returns></returns>
            public static object InvokeMethod(object instance, string methodName, params object[] paras)
            {
                var privateObject = new PrivateObject(instance);
                return privateObject.Invoke(methodName, paras);
            }
        }
    PrivateUnitTestUtil

    在测试项目中调用

     [TestClass]
        public class PrivateUnitTestUtilTests
        {
            [TestMethod]
            public void InvokeMethodTest()
            {
                var instance = new DemoClass();
                instance.Name = "111111";
                DateTime time = DateTime.Now;
                var ret = (string) PrivateUnitTestUtil.InvokeMethod(instance, "PrivateMethod", time);
                Assert.AreEqual(ret, "姓名:{0} 年龄:{1} 时间:{2}".FormatWith(instance.Name, instance.Age, time.Year));
            }
        }
    PrivateUnitTestUtilTests

    更多的调用方式可以慢慢补充,相关文件下载地址:http://download.csdn.net/detail/zbl131/9493247

  • 相关阅读:
    PHP实现对站点内容外部链接的过滤方法
    PHP常用技术文之文件操作和目录操作总结
    PHP实现手机号码中间四位用星号(*)隐藏的自定义函数分享
    PHP如何快速读取大文件
    php使用json_encode后出现中文乱码的解决方法
    redis在PHP中的基本使用
    等差数列的概念和性质
    构造数列中的常见变形总结
    用几何画板制作函数图像的动态伸缩效果
    用几何画板制作函数图像的动态平移效果
  • 原文地址:https://www.cnblogs.com/zeroes/p/PrivateReflection.html
Copyright © 2011-2022 走看看