VS2005對私有方法的單元進(jìn)行測試

2010-08-28 10:48:27來源:西部e網(wǎng)作者:

  使用 Visual Studio 對公共方法進(jìn)行單元測試,跟以前 NUnit 一樣,都是引用需要的類,然后對公共方法進(jìn)行測試。

  但是 Visual Studio 還可以對類的私有方法進(jìn)行測試。而Visual Studio 不允許測試代碼跟實(shí)際代碼放在一個項(xiàng)目中,我們來看看是Visual Studio UnitTest如何做的。

  比如我們有這樣一個私有方法

namespace ClassLibrary1{
 public class DivisionClass{
  private int Divide_private(int numerator, int denominator){
   return numerator / denominator;
  }
 }
}

  我們只要在這個私有方法的右鍵菜單中選擇 創(chuàng)建單元測試,系統(tǒng)就自動產(chǎn)生了這個私有方法的單元測試代碼。

  下面我們來分析產(chǎn)生的單元測試代碼,看Visual Studio UnitTest 是如何對私有方法進(jìn)行單元測試的

  簡單來說,Visual Studio UnitTest 生成私有方法的單元測試時,將自動創(chuàng)建一個私有訪問器。私有訪問器是測試方法用于訪問私有代碼的方法。單元測試生成對私有訪問器的調(diào)用,然后通過私有訪問器來調(diào)用私有方法。私有訪問器駐留在測試項(xiàng)目中的文件中;因此將被編譯為測試項(xiàng)目程序集。

  具體來看測試項(xiàng)目:

  首先我們可以看到一個名為 VSCodeGenAccessors.cs 的新文件被創(chuàng)建,

  這個文件包含兩個類:

  internal 類型的 BaseAccessor 類 和 派生自它的 ClassLibrary1_DivisionClassAccessor 類

  BaseAccessor 類 是通用的訪問器基類。

  ClassLibrary1_DivisionClassAccessor 類 則是對你要訪問類的私有方法進(jìn)行了反射封裝,這樣你就可以通過操作這個類來操作該私有方法了。如下面代碼:

using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace TestProject1{
 [System.Diagnostics.DebuggerStepThrough()]
 [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TestTools.UnitTestGeneration", "1.0.0.0")]
 internal class BaseAccessor {

  protected Microsoft.VisualStudio.TestTools.UnitTesting.PrivateObject m_privateObject;

  protected BaseAccessor(object target, Microsoft.VisualStudio.TestTools.UnitTesting.PrivateType type) {
   m_privateObject = new Microsoft.VisualStudio.TestTools.UnitTesting.PrivateObject(target, type);
  }

  protected BaseAccessor(Microsoft.VisualStudio.TestTools.UnitTesting.PrivateType type) :
  this(null, type) {}

  internal virtual object Target {
   get {
    return m_privateObject.Target;
   }
  }

  public override string ToString() {
   return this.Target.ToString();
  }

  public override bool Equals(object obj) {
   if (typeof(BaseAccessor).IsInstanceOfType(obj)) {
    obj = ((BaseAccessor)(obj)).Target;
   }
   return this.Target.Equals(obj);
  }

  public override int GetHashCode() {
   return this.Target.GetHashCode();
  }
 }

 [System.Diagnostics.DebuggerStepThrough()]
 [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TestTools.UnitTestGeneration", "1.0.0.0")]
 internal class ClassLibrary1_DivisionClassAccessor : BaseAccessor {

 protected static Microsoft.VisualStudio.TestTools.UnitTesting.PrivateType m_privateType = new Microsoft.VisualStudio.TestTools.UnitTesting.PrivateType(typeof(global::ClassLibrary1.DivisionClass));

 internal ClassLibrary1_DivisionClassAccessor(global::ClassLibrary1.DivisionClass target) :
 base(target, m_privateType) {}

 internal int Divide_private(int numerator, int denominator) {
  object[] args = new object[] {
   numerator,
   denominator};
  int ret = ((int)(m_privateObject.Invoke("Divide_private", new System.Type[] {
   typeof(int),
   typeof(int)}, args)));
   return ret;
  } 
 }
}

  注意:當(dāng)您更改正在測試的代碼文件中的私有方法時,這個訪問器可能無法正常工作,需要重新生成專用訪問器(ClassLibrary1_DivisionClassAccessor 類)。

  整理一下就是:

  這個訪問器,是通過反射的方式實(shí)現(xiàn)的。

  VSUT利用自動代碼生成技術(shù),在單元測試項(xiàng)目中先來給你要測試的類生成一個名字叫XXXAccessor的訪問器。

  這個訪問器會把需要測試類的需要測試的私有方法暴露出來,這種方式,無論是私有還是公共的屬性和方法。這種方式可以很方便的給測試方法搭建測試環(huán)境,MOCK對象的注入也容易了。在測試調(diào)用的時候,就簡單的只有下面的代碼了:

[DeploymentItem("ClassLibrary1.dll")]
[TestMethod()]
public void Divide_privateTest()
{
 DivisionClass target = new DivisionClass();
 TestProject1.ClassLibrary1_DivisionClassAccessor accessor = new  TestProject1.ClassLibrary1_DivisionClassAccessor(target);
 int numerator = 4;
 int denominator = 0;
 int expected = 0;
 int actual;
 actual = accessor.Divide_private(numerator, denominator);
 Assert.AreEqual(expected, actual, "ClassLibrary1.DivisionClass.Divide_private 未返回所需的值。");
 Assert.Inconclusive("驗(yàn)證此測試方法的正確性。");
}
關(guān)鍵詞:VS.net

贊助商鏈接: