2011-03-22 36 views
22

我正在测试作为层次结构一部分的类。我一直在设置我的测试类与测试对象,并允许访问该对象的PrivateObject。当我尝试访问父类的私有成员时,我收到异常。如何使用PrivateObject访问我的类和它的父类的私有成员?

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

有什么办法可以做到这一点,也许通过在私有对象的Get *方法上使用绑定标志参数?

我尝试使用自动生成的Accessor类(右键单击主类Create Private Accessor)。然而,情况更糟糕:它显示了一个我可以读取的属性,但它引发了与PrivateObject相同的异常,并且没有其他选项可以用来修复异常(绑定标志或其他选项)。

这是我的示例测试代码。我希望有一些方法来构建和使用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<int>(0, (int)priv.GetFieldOrProperty("one", flags)); // System.MissingMethodException: Method 'PrivateObjectTester.SubClass.one' not found. 
     Assert.AreNotEqual<int>(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<int>(0, (int)priv.GetFieldOrProperty("one", flags)); 
     Assert.AreNotEqual<int>(0, (int)priv.GetFieldOrProperty("two", flags)); // System.MissingMethodException: Method 'PrivateObjectTester.BaseClass.two' not found. 
    } 
} 
+1

正如旁注所示,您可以使用PrivateObject访问受保护的成员 – 2012-09-04 19:07:27

回答

28

我没有找到答案,所以这就是我最终做的。我为类的层次结构的每个级别创建了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<int>(0, (int)privBase.GetFieldOrProperty("one")); 
     Assert.AreNotEqual<int>(0, (int)privSub.GetFieldOrProperty("two")); 
    } 
} 
+0

这是实现它的正确方法。 – Thought 2017-12-04 17:37:52

8

这可能不是您想要的答案......但您不应该在一种方法中首先测试两个类。你应该一次只能测试一个课程。如果你觉得需要这样做,那么我猜你的代码需要重构。但是因为我不知道你的真实代码问题,所以我不能肯定地说

+2

我没有真正测试两个类,我正在测试一个类,以及它的基类。在我的情况下,我正在测试一些清理行为:当对象清理自己时,我检查所有清理任务是否正确发生,其中一些在基础中,一些在子类中。你是对的,理想情况下,我应该自己测试基类清除,但是这个测试的一部分是测试异常清除,只有在这个特定的子类中才会发生。 – 2011-04-15 18:36:33

1

当涉及到处理继承问题时,PrivateObject在“愚蠢的”一面。不幸的是,它的方法不是虚拟的,所以没有简单的方法来改变这种行为。你基本上有两个选择:或者生活在限制之中,或者创建你自己的私人访问器助手,它可以透明地处理继承的成员。

1
// 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<string> parameter = (Collection<string>)helperobject1.GetFieldOrProperty("parameters"); 
1

安德烈·佩纳写道。为什么你想通过Subclass测试Baseclass的private成员。您无法在您的子类的正常代码中访问这些成员。您必须使Properties成员protected能够从子类访问它们。

然后你也可以使用PrivateObject测试这些成员。

+0

考虑您正在为抽象类中的公共功能编写测试。为了测试这个类,你创建了一个你可以实例化的派生模拟类。在这种情况下,您可能仍然想要使用私有变量的值(例如,由UI绑定的属性,该属性没有公共/受保护的setter)。 我不同意改变成员以适应测试的方便性就是答案。 – kodjeff1 2014-08-04 19:38:45

1

我想做同样的事情,我做了这种扩展方法。现在它运作良好。我最初的想法是从你的帖子。谢谢!

https://github.com/cactuaroid/PrivateObjectExtensions

它在做什么基本上是由Type.GetFields()Type.GetProperties()寻找成员所有者递归,然后创建PrivateObject(或PrivateType)为正确类型访问成员。

相关问题