背景

年龄大点的程序员都知道在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. 自制Unity小游戏TankHero-2D(4)关卡+小地图图标+碰撞条件分析

    自制Unity小游戏TankHero-2D(4)关卡+小地图图标+碰撞条件分析 我在做这样一个坦克游戏,是仿照(http://game.kid.qq.com/a/20140221/028931.htm ...

  2. 最全数据结构详述: List VS IEnumerable VS IQueryable VS ICollection VS IDictionary

    本文对常用的数据结构详述:Array, ArrayList,List,IList,ICollection, Stack, Queue, HashTable, Dictionary, IQueryabl ...

  3. Java Socket Server的演进 (一)

    最近在看一些网络服务器的设计, 本文就从起源的角度介绍一下现代网络服务器处理并发连接的思路, 例子就用java提供的API. 1.单线程同步阻塞式服务器及操作系统API 此种是最简单的socket服务 ...

  4. Redis数据库的安装配置方

    转载于:http://www.itxuexiwang.com/a/shujukujishu/redis/2016/0216/100.html?1455869650 redis 是一个高性能的key-v ...

  5. 爱上MVC~一个Action多套View模版的设计

    回到目录 模块化 这个问题是在做模块化设计时出现的,在Lind.DDD.Plugins模块里,需要对应的模块实体,模块管理者,模块标识接口等,开发时,如果你的功能点属于一个模块,需要实现IPlugin ...

  6. inoic start projectname sidemenu报错 - Error: Cannot find module 'lodash._baseslice'

    inoic start projectname sidemenu报错 - Error: Cannot find module 'lodash._baseslice' 在公司的电脑上出现过这个错误,后来 ...

  7. cordova填坑

    cordova填坑

  8. php技术之路

    按照了解的很多PHP/LNMP程序员的发展轨迹,结合个人经验体会,抽象出很多程序员对未来的迷漫,特别对技术学习的盲目和慌乱,简单梳理了这个每个阶段PHP程序员的技术要求,来帮助很多PHP程序做对照设定 ...

  9. Kruskal算法(二)之 C++详解

    本章是克鲁斯卡尔算法的C++实现. 目录 1. 最小生成树 2. 克鲁斯卡尔算法介绍 3. 克鲁斯卡尔算法图解 4. 克鲁斯卡尔算法分析 5. 克鲁斯卡尔算法的代码说明 6. 克鲁斯卡尔算法的源码 转 ...

  10. php基础教程-数据类型

    PHP 支持八种原始类型(type). 四种标量类型: string(字符串) integer(整型) float(浮点型,也作 double ) boolean(布尔型) 两种复合类型: array ...