如何使用PrivateObject访问我的类及其父级的私有成员?

我正在测试一个属于层次结构的类。 我一直在设置我的测试类和被测对象,以及一个允许访问该对象的PrivateObject 。 当我尝试访问父类的私有成员时,我遇到exception。

到目前为止,我发现的唯一解决方法是将指定基类的PrivateObject传递给PrivateObject构造函数,但是它不适用于子类的私有成员。

有没有办法可以做到这一点,也许是通过在Private对象的Get *方法上使用binding flags参数?

我尝试使用自动生成的Accessor类(右键单击主类,Create Private Accessor)。 但是,情况更糟:它显示了我可以读取的属性,但它抛出与PrivateObject相同的exception,并且没有其他选项可以使用(绑定标志或诸如此类)来修复exception。

这是我的示例测试代码。 我希望有一些方法来构造和使用PrivateObject来检索这两个字段。

 public class BaseClass { private int one = 1; } public class SubClass : BaseClass { private int two = 2; } [TestClass] public class UnitTest1 { BindingFlags flags = BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; [TestMethod] public void TestMethod1() { SubClass test = new SubClass(); PrivateObject priv = new PrivateObject(test); Assert.AreNotEqual(0, (int)priv.GetFieldOrProperty("one", flags)); // System.MissingMethodException: Method 'PrivateObjectTester.SubClass.one' not found. Assert.AreNotEqual(0, (int)priv.GetFieldOrProperty("two", flags)); } [TestMethod] public void TestMethod2() { SubClass test = new SubClass(); PrivateObject priv = new PrivateObject(test, new PrivateType(typeof(BaseClass))); Assert.AreNotEqual(0, (int)priv.GetFieldOrProperty("one", flags)); Assert.AreNotEqual(0, (int)priv.GetFieldOrProperty("two", flags)); // System.MissingMethodException: Method 'PrivateObjectTester.BaseClass.two' not found. } } 

我找不到答案,所以这就是我最终要做的事情。 我为类的层次结构的每个级别创建了PrivateObjects ,在编写使用正确的测试用例时我只需要小心。

 public class BaseClass { private int one = 1; } public class SubClass : BaseClass { private int two = 2; } [TestClass] public class UnitTest1 { [TestMethod] public void TestMethod() { SubClass test = new SubClass(); PrivateObject privSub = new PrivateObject(test, new PrivateType(typeof(SubClass))); PrivateObject privBase = new PrivateObject(test, new PrivateType(typeof(BaseClass))); Assert.AreNotEqual(0, (int)privBase.GetFieldOrProperty("one")); Assert.AreNotEqual(0, (int)privSub.GetFieldOrProperty("two")); } } 

这可能不是你想要的答案……但你不应该首先在一种方法中测试这两个类。 你应该一次只测试一个class级。 如果你觉得有必要这样做,那么我猜你的代码需要重构。 但由于我不知道你的现实代码问题,我不能肯定地说

在处理inheritance时,PrivateObject有点“哑”。 不幸的是,它的方法不是虚拟的,因此没有简单的方法来改变这种行为。 您基本上有两个选择:要么有限制,要么创建自己的私有访问者帮助程序,可以透明地处理inheritance的成员。

 // create an instance of class SearchPlanogramsBuilder: SearchPlanogramsBuilder searchPlanogramBuilder = new SearchPlanogramsBuilder(); // executing the method BuildSearchParameters(return type is void) with input searchPlanoGramsFilters: searchPlanogramBuilder.BuildSearchParameters(searchPlanoGramsFilters); // create privateobject and pass instance created for the class: PrivateObject helperobject1 = new PrivateObject(searchPlanogramBuilder); // type cast exactly as parameter(which is private variable) in the method: Collection parameter = (Collection)helperobject1.GetFieldOrProperty("parameters"); 

正如安德烈佩纳所写的那样。 您为什么要通过子类测试Baseclass的private成员。 您也无法在子类的普通代码中访问这些成员。 您必须使属性成员protected才能从子类访问它们。

然后,您还可以使用PrivateObject测试这些成员。

我想做同样的事情,我做了这个扩展方法。 现在效果很好。 我最初的想法来自你的post。 谢谢!

https://github.com/cactuaroid/PrivateObjectExtensions

它正在做的基本上是递归地通过Type.GetFields()Type.GetProperties()查找成员所有者,然后创建PrivateObject(或PrivateType)作为访问该成员的正确类型。

使用PrivateType指定所需的类型并使用不同的PrivateObject构造函数:

 var test = new SubClass(); var privateType = new PrivateType(typeof(BaseClass)); var privateObject = new PrivateObject(test, privateType); // privateObject.GetFieldOrProperty("one", flags)