2017-09-26 40 views
-5

我發現了一種奇妙的方法來測試私有方法。如何在C#中的PrivateObject上創建類型安全性

這很好,除了我不喜歡如何將字符串輸入到方法名稱中。有沒有辦法建立一個「安全網」?我想輸入方法名稱,以便如果方法不存在於對象上,編譯器可以拋出編譯器時間錯誤。

私有方法:

public class BankAccount 
{ 
    //Private method to test 
    private bool VerifyAmount(double amount) 
    { 
     return (amount <= 1000); 
    } 
} 

單元測試:

[TestMethod()]   
public void VerifyAmountTest() 
{ 
    //Using PrivateObject class 
    PrivateObject privateHelperObject = new PrivateObject(typeof(BankAccount));        
    double amount = 500F; 
    bool expected = true; 
    bool actual; 
    actual = (bool)privateHelperObject.Invoke("VerifyAmount", amount);    
    Assert.AreEqual(expected, actual);    
} 

我知道,有些人認爲我們不應該單元測試私有方法。這不是這個問題的目的,所以我們不要討論這個問題並留在主題上。

+6

你認爲你不應該測試私有方法嗎? – CodeCaster

回答

-2

我是對的,你想檢查存在的private方法上.Net對象?

然後挑下列情形之一的,以提取實例的所有方法:

案例1如果你不關心的方法簽名:

var typeOfObj = typeof(BancAccount) 
       .GetMethods(
       BindingFlags.NonPublic | 
       BindingFlags.Instance) 
       .Any(method => method.Name == testedName) 

案例2如果您需要指定確切的簽名,然後使用 - typeof(BancAccount).GetMethod(testedName, <types of arguments>)

+0

不,他們的問題是「我怎樣才能在不借助字符串的情況下引用私有財產」_。 – CodeCaster

+0

沒有。他想測試私人方法,而現在他正在使用反射來完成名稱。 – JuanR

+0

在這種情況下,「testedName」不是代表方法名稱的字符串嗎? – Maderas

0

當你單元測試一個班級,你基本上把你的消費者的帽子,並打電話給暴露該類的方法用於驗證該類是否完成它聲稱的操作。

例如,使用您的BankAccount類考慮這個例子:

public class BankAccount 
{ 
    public Widthdrawal WithdrawMoney(double amount) 
    { 
      if(!VerifyAmount(amount)) 
       throw new InvalidOperationException("Minimum dispensed is $1,000!"); 
      //Do some stuff here 
      return new Withdrawal(1000); 
    } 
    private bool VerifyAmount(double amount) 
    { 
     return (amount <= 1000); 
    } 

} 

然後,您可以測試一些東西。例如:

  1. 有效金額會導致提款。
  2. 無效的數量會導致無效的操作異常。

你的檢查:

[TestMethod] 
public void Verify_Valid_Amount_Results_In_Widtdrawal() 
{ 
    var bankAccount = new BankAccount(); 
    var withdrawal = bankAccount.WithdrawMoney(1200); 
    Assert.IsNotNull(withdrawal); 
    Assert.AreEqual(1200, withdrawal); 
} 


[TestMethod] 
[ExpectedException(typeof(InvalidOperationException))] 
public void Verify_Valid_Amount_Results_In_Exception() 
{ 
    var bankAccount = new BankAccount(); 
    var withdrawal = bankAccount.WithdrawMoney(800); 
} 

正如你所看到的,你測試使用的私有方法,而不是私有方法本身的funcionality。

如果驗證該方法非常重要,您可以將其公開或將量驗證概念抽象爲暴露此方法的另一個類,並可以單獨進行單元測試。

+1

關於我們應該測試的單元有很多不同的觀點。你沒有回答我的問題。你離題了。 – Maderas

+1

認爲_unit testing_ == _testing class_的公共接口是一種常見的誤解。正如名稱本身所說,它是「測試_unit_」,其中_unit_是funcionality_的一個單位。測試私人/內部方法是完全合法的。在一些像C#或Java這樣的語言中,它更加困難(你必須使用Reflection和硬編碼的字符串,它很棘手和無聊),在其他語言(Python)中你根本沒有私有方法,所以你認爲所有方法都是「私有」用下劃線表示,但這只是一個慣例,你可以像公共的一樣訪問和測試它們。 –

+0

@MassimilianoKraus:讓我們不要把它變成一場哲學戰爭。這將是我最後的評論。如果您想測試方法本身,您可以隨時將其公開或抽象爲另一個類的驗證的概念,然後您可以將其傳遞給原始對象。這樣你可以分別驗證金額邏輯。您可能會將Python缺乏訪問控制看作一項功能。我認爲這是一個小姐。無論如何,對他自己的每一個。 :-) – JuanR

相關問題