2017-09-26 39 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

相关问题