2013-10-07 63 views
5

我有一個大的應用程序從配置文件讀取一些參數。修改私有靜態只讀字段

我在寫單元測試,其產生既參數,並從配置文件讀取值執行某些操作後的結果一類:

internal static class Password 
{ 
    private static readonly byte PASSWORD_PRIVATE_KEY 
     = ConfigFile.ReadByte("PASSWORD_PRIVATE_KEY"); 

    public static byte Generate(byte passwordPublicKey); 
} 

在我的單元測試,我知道值Password.Generate()方法應返回給定PASSWORD_PRIVATE_KEYPASSWORD_PUBLIC_KEY。但我想用在單元測試類中定義的,而不是在配置文件中PASSWORD_PRIVATE_KEY值:

[TestMethod] 
public void PasswordGenerate_CalculatedProperly() 
{ 
    byte passwordPublicKey = 0x22; 
    Password_Accessor.PASSWORD_PRIVATE_KEY = 0xF0; 
    byte expectedGenerated = 0xAA; 

    byte generated = Password_Accessor.Generate(passwordPublicKey); 

    Assert.AreEqual(expectedGenerated, generated); 
} 

有沒有一種方法,我可以寫private static readonly直通代碼,所以我不必依賴任何配置文件進行測試?

+0

請注意這個問題是不同的這個:http://stackoverflow.com/q/6851816/1192381 –

+0

規範的答案是「不要使用靜態初始化'私人靜態'領域」 - 重構「密碼」類所以它從合作者類獲得'PASSWORD_PRIVATE_KEY'的值,然後你可以模擬它。在這種情況下,似乎使得'ConfigFile'非靜態將是答案。 – millimoose

+2

一般來說,'static'是單元測試的死敵。 – millimoose

回答

6

要做到這一點乾淨的方式,你需要使Password更可測試。要做到這一點,可以考慮這種設計:

internal static class Password 
{ 
    public static void Configure(IPrivateKeyProvider keyProvider) 
    { 
     keyProvider = keyProvider; 
    } 

    public static byte Generate(byte passwordPublicKey); // use keyProvider 

    private static IPrivateKeyProvider* keyProvider; 
} 

internal interface IPrivateKeyProvider 
{ 
    byte GetPrivateKey(); 
} 

internal class ConfigPrivateKeyProvider : IPrivateKeyProvider 
{ 
    private static readonly byte PASSWORD_PRIVATE_KEY 
     = ConfigFile.ReadByte("PASSWORD_PRIVATE_KEY"); 

    public byte GetPrivateKey() 
    { 
     return PASSWORD_PRIVATE_KEY; 
    } 
} 

internal class PrivateKeyProviderStub : IPrivateKeyProvider 
{ 
    public PrivateKeyProviderStub(byte privateKey) 
    { 
     this.privateKey = privateKey; 
    } 

    public byte GetPrivateKey() 
    { 
     return this.privateKey; 
    } 
} 

現在你的產品代碼可以使用ConfigPrivateKeyProvider和測試可以使用PrivateKeyProviderStub

Password作爲靜態類保留有點簡化。我建議將這個重構成一個普通的類,如果合適的話,也可以是單例。

還要注意的是,有很多測試框架允許在飛行中方便地生成模擬和存根(例如Rhino Mocks),因此不需要手動執行PrivateKeyProviderStub

+0

謝謝你的回答。我會採用這種方法,但是使用模擬ConfigFile類來替代,所以我不必修改測試的Password類。 –

1

編號 沒有辦法訪問私人領域。

對於單元測試,你通常想訪問內部的東西,你可以使用InternalsVisibleTo來做到這一點。但即使是私人成員保持私密。你可能想爲這些字段定義一個getter。

編輯:使用一些繁瑣的語法,您可以使用PrivateObjects訪問專用字段。

+0

使用' _Accessor'包裝我已經寫入內部類中的專用字段的權限。這樣就完成了一個項目中正在測試的應用程序和另一個項目中的單元測試類。 所以,我認爲問題不在於這些字段是「private」,而是它們是「靜態只讀」,並且在測試它們時已經被賦予了一個值。 –

2

我不是一位.NET專家,因此請帶上一點鹽。

單元測試的價值之一就是向你展示你需要重新考慮你的代碼。如果難以測試,則需要重寫。

找出將文件的抽象注入Password的方法,然後創建該抽象的模擬實現(例如,使用MoqRhino Mocks)。

但是就像你現在這樣,我不認爲有任何解決方法使用文件。你只需告訴你的測試看看另一個文件。

希望有所幫助。

+0

「你只需告訴你的測試看看另一個文件。」謝謝。我會做。有一個'ConfigFile'的模擬器,它實際上不會從配置文件讀取,但返回可以在'Password'類調用'ReadByte()'之前以編程方式分配的值。 –

相關問題