从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

时间: 2024-08-01 10:28:28

从vs2010的UnitTestFramework类库提取私有方法反射调用的方法的相关文章

VS2010 F5调试时出现:“ 尝试运行项目时出错:未捕获通过反射调用的方法引发的异常”解决

S2010 F5调试时出现 尝试运行项目时出错:未捕获通过反射调用的方法引发的异常 两个解决方法:1) 打开项目属性,选择调试选项卡,将“启用非托管代码调试”一项钩上.2) 打开项目属性,选择调试选项卡,将“启用Visual Studio宿主进程“一项钩掉. 原文地址:https://www.cnblogs.com/gisoracle/p/9690123.html

java动态加载指定的类或者jar包反射调用其方法

序言 有时候,项目中会用到java动态加载指定的类或者jar包反射调用其方法来达到模块的分离,使各个功能之间耦合性大大降低,更加的模块化,代码利用率更高.模式中的代理模式就用到java的这一机制.下边就让我们通过代码来看看如何实现此功能. 代码详细 package loadjarclass; import java.io.File; import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoad

java动态载入指定的类或者jar包反射调用其方法

序言 有时候.项目中会用到java动态载入指定的类或者jar包反射调用其方法来达到模块的分离,使各个功能之间耦合性大大减少,更加的模块化.代码利用率更高.模式中的代理模式就用到java的这一机制. 下边就让我们通过代码来看看怎样实现此功能. 代码具体 package loadjarclass; import java.io.File; import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoa

反射-优化及程序集等(用委托的方式调用需要反射调用的方法(或者属性、字段),而不去使用Invoke方法)

创建Delegate (1).Delegate.CreateDelegate(Type, MethodInfo) : 创建指定类型的静态方法, 1.Type(委托类型) 2.MethodInfo(要创建的静态方法的信息,通过类的type.GetMethod( funcName , BindingFlags.IgnoreCase | BindingFlags.Static | BindingFlags.Public )获取) 3.例:typeof(string).GetMethod(“Equals

springMVC在普通方法中调用service方法

SpringContextUtil类 package com.common.util; import org.springframework.beans.BeansException;import org.springframework.beans.factory.NoSuchBeanDefinitionException;import org.springframework.context.ApplicationContext;import org.springframework.contex

对JAVA Bean使用PropertyDescriptor反射调用JAVA方法低耦合

对于符合JAVA Bean规范的bean,调用其方法应优先使用java.beans.PropertyDescriptor获取Method进行方法调用,以获得更大的可维护性. public void gridColumnFilter(List<?> list, Map<String, Object> dataMap){    for (Iterator<?> iterator = list.iterator(); iterator.hasNext();) { Object

对JAVA Bean使用PropertyDescriptor反射调用JAVA方法

对于符合JAVA Bean规范的bean,调用其方法应优先使用java.beans.PropertyDescriptor获取Method进行方法调用,以获得更大的可维护性. 示比例如以下: NonCopyLogEntity ncl = new NonCopyLogEntity(); for (int i = 0; i < st.length; i++) { String fieldName = NonCopyLogEntity.fieldPosMap.get(i + 1); PropertyDe

C#,动态加载DLL,通过反射,调用参数,方法,窗体

.net中常会用到动态加载DLL,而DLL中可能包含各种参数.方法.窗体,如何来调用动态加载这些参数.方法.窗体呢? 在C#中,我们要使用反射,首先要搞清楚以下命名空间中几个类的关系: System.Reflection命名空间 (1)   AppDomain:应用程序域,可以将其理解为一组程序集的逻辑容器 (2)   Assembly:程序集类 (3)   Module:模块类 (4)   Type:使用反射得到类型信息的最核心的类 他们之间是一种从属关系,也就是说,一个AppDomain可以

重写父类方法与调用父类方法

重写父类方法 所谓重写,就是子类中,有一个和父类相同名字的方法,在子类中的方法会覆盖掉父类中同名的方法, #coding=utf-8 class Cat(object): def sayHello(self): print("halou-------1") class Bosi(Cat): def sayHello(self): print("halou-------2") bosi = Bosi() bosi.sayHello() 调用父类的方法 #coding=