unit testingC#中的私有方法

Visual Studio允许通过自动生成的访问器类对私有方法进行unit testing。 我写了一个testing成功编译的私有方法,但在运行时失败。 代码的相当小的版本和testing是:

//in project MyProj class TypeA { private List<TypeB> myList = new List<TypeB>(); private class TypeB { public TypeB() { } } public TypeA() { } private void MyFunc() { //processing of myList that changes state of instance } } //in project TestMyProj public void MyFuncTest() { TypeA_Accessor target = new TypeA_Accessor(); //following line is the one that throws exception target.myList.Add(new TypeA_Accessor.TypeB()); target.MyFunc(); //check changed state of target } 

运行时错误是:

 Object of type System.Collections.Generic.List`1[MyProj.TypeA.TypeA_Accessor+TypeB]' cannot be converted to type 'System.Collections.Generic.List`1[MyProj.TypeA.TypeA+TypeB]'. 

根据intellisense – 因此我猜编译器 – 目标types是TypeA_Accessor。 但在运行时它是TypeAtypes,因此列表添加失败。

有什么办法可以阻止这个错误? 或者更可能的是,其他人有什么其他的build议(我预测也许“不testing私有方法”,“没有unit testing操纵对象的状态”)。

是的,不要testing私有方法….unit testing的思想是通过公共的“API”来testing这个单元。

如果你发现你需要testing大量的私人行为,那么很可能你会在你正在testing的类中隐藏一个新的“类”,将其提取出来并通过其公共接口进行testing。

一个build议/思考工具…..有一个想法,任何方法都不应该是私人的。 意味着所有的方法应该生活在一个对象的公共接口上……如果你觉得你需要把它变成私有的,它很可能存在于另一个对象上。

这个build议在实践中并不完全正确,但是它的build议大多是好的,而且往往会促使人们将对象分解成更小的对象。

您可以使用PrivateObject类

 Class target = new Class(); PrivateObject obj = new PrivateObject(target); var retVal = obj.Invoke("PrivateMethod"); Assert.AreEqual(retVal); 

“没有什么叫做标准或最佳实践,可能它们只是stream行的意见”。

这个讨论也是如此。

在这里输入图像描述

这一切都取决于你认为是一个单位,如果你认为单位是一个类,那么你只会打公众的方法。 如果你认为UNIT是一系列的代码打私人方法不会让你感到内疚。

如果你想调用私有方法,你可以使用“PrivateObject”类并调用invoke方法。 您可以观看这个深入的YouTubevideo( http://www.youtube.com/watch?v=Vq6Gcs9LrPQ ),其中显示了如何使用“PrivateObject”,并讨论了私有方法的testing是否合乎逻辑。

这里的另一个想法是将testing扩展到“内部”类/方法,给予这种testing更多的白盒感。 你可以在程序集上使用InternalsVisibleToAttribute来公开这些单独的unit testing模块。

您可以围绕包含您要testing的私有方法的类创build一个包装类。 这个包装类包含一个名为Call_MyPrivateFunction的公共方法,该方法又调用其基类的私有函数。

请注意,方法访问级别更改为[protected]

代码示例:

 public class Order { public int Quantity { get; set; } protected bool OrderIsBig () { //This is the method we want to test. It needs to be protected in stead of private. Else... no cigar return Quantity > 100; } } //Use this wrapper class in your unit test. public class FakeOrder : Order { public bool Call_OrderIsBig() { //This makes the actual call to the protected method "OrderIsBig" return OrderIsBig(); } } 

unit testing代码可能如下所示:

 FakeOrder order = new FakeOrder(); order.Quantity = 200; bool isBig = order.Call_OrderIsBig(); //Make a call to a public method of the FakeOrder class which in turn makes a call to the protected method. 

testing私人方法的一种方法是通过反思。 这也适用于NUnit和XUnit:

 MyObject objUnderTest = new MyObject(); MethodInfo methodInfo = typeof(MyObject).GetMethod("SomePrivateMethod", BindingFlags.NonPublic | BindingFlags.Instance); object[] parameters = {"parameters here"}; methodInfo.Invoke(objUnderTest, parameters); 

在VS 2005/2008中,你可以使用私有的访问器来testing私有成员,但是这种方式在VS的后期版本中消失