背景

年龄大点的程序员都知道在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 = ; // 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",)
{
} 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 = "";
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

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

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

    VS2010 F5调试时出现 尝试运行项目时出错:未捕获通过反射调用的方法引发的异常 两个解决方法:1) 打开项目属性,选择调试选项卡,将“启用非托管代码调试”一项钩上.2) 打开项目属性,选择调试选 ...

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

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

  3. JavaSE复习日记 : 方法的调用和方法的重载

    /* * 方法的调用和方法重载 */ /* * 什么是方法? * 方法就是一个有名字的代码段; * 方法的调用: * 在方法里调用另外一个方法里面的东西就是方法调用; * 或者可以认为"另外 ...

  4. JNI C反射调用java方法

    前面记录了调用C的学习笔记,现在来记录一下C反射调用Java的笔记.JNI开发学习之调用C方法 Android开发中调用一个类中没有公开的方法,可以进行反射调用,而JNI开发中C调用java的方法也是 ...

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

    序言 有时候.项目中会用到java动态载入指定的类或者jar包反射调用其方法来达到模块的分离,使各个功能之间耦合性大大减少,更加的模块化.代码利用率更高.模式中的代理模式就用到java的这一机制. 下 ...

  6. Spring AOP开发时如何得到某个方法内调用的方法的代理对象?

    Spring AOP开发时如何得到某个方法内调用的方法的代理对象? 问题阅读起来拗口,看代码 在方法中调用其他方法很常见,也经常使用,如果在一个方法内部调用其他方法,比如 public class U ...

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

    对于符合JAVA Bean规范的bean,调用其方法应优先使用java.beans.PropertyDescriptor获取Method进行方法调用,以获得更大的可维护性. 示比例如以下: NonCo ...

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

    SpringContextUtil类 package com.common.util; import org.springframework.beans.BeansException;import o ...

  9. UnityTips:使用反射调用内部方法拓展编辑器

    大家都知道Unity是一个C/C++的游戏引擎,C#只是Unity提供的脚本层.因此大部分功能都是通过C#来调用底层的C++代码的.而一些朋友可能不知道的是,其实Unity的C#代码中也有很多方法是我 ...

随机推荐

  1. [HIMCM暑期班]第4课: 扑克牌问题

    假设跟你玩这样一个游戏: 拿一副52张牌的扑克,洗均匀.每次展示一张牌,如果是红心或者方块,你就赢10块钱:如果是黑桃或者草花,你就输10块钱.你可以选择在任何时候终止此游戏.问如何确保利益最大化? ...

  2. redis系列-主从复制

    redis自身提供了主从的机制,通过配置可以实现服务的备份(Master->Slave). 配置项 slaveof <masterip> <masterport> mas ...

  3. SQLServer数据库还原提示 数据库正在使用,无法获得独占访问权

    还原数据库的时候提示下图的错误:

  4. 用scrollTop制作一个自动滚动公告栏

    我们在浏览网页时,经常会看到会一些滚动的栏目,比如向上滚动的公告.新闻等.其实他们的制作都不难,只要学了基础的html.css.javascript就可以做出来,用JavaScript的scrollT ...

  5. javascript_basic_02之数据类型、分支结构

    1.弱类型:声明无需指定数据类型,由值决定,查看变量数据类型:typeof(变量): 2.隐式转换:任何数据类型与string类型相加,结果为string类型: 3.显式(强制)转换: ①toStri ...

  6. Ubuntu14.04安装pip及配置

    安装pip: wget https://bootstrap.pypa.io/get-pip.py --no-check-certificate sudo python get-pip.py 建立软连接 ...

  7. HTTP与AJAX深入揭秘,不使用AJAX实现页面无刷新

    AJAX的原理是什么? 实际上就是发起HTTP请求,既然就是发起HTTP请求,那只要我们能够实现发起HTTP请求就可以在不使用AJAX的情况下实现相同的效果. 在前端有好多方式可以发起HTTP请求,比 ...

  8. 将 PAGE_VERIFY 数据库选项设置为 CHECKSUM

    此规则检查 PAGE_VERIFY 数据库选项是否已设置为 CHECKSUM.为 PAGE_VERIFY 数据库选项启用 CHECKSUM 后,SQL Server 数据库引擎会在向磁盘中写入页面时计 ...

  9. C# LINQ需求实现演化

    Linq是C#3.0引入的,在C#2.0实现从集合中过滤符合条件的记录实现方式. 假设有一个Book类,以及一个Book类的集合,现在需要从集合中查找出单价大于50的Book. 1.固定查询字段的实现 ...

  10. SQL PASS将于8月24日在北京中医药大学举办线下活动

    活动主题:复制架构的实现和调优以及SQL Server BI在传统行业的应用 地点:北三环东路11号 北京中医药大学 白色的1号楼教学楼后楼5层511房间 时间:2013年8月24日 9:00-12: ...