2013-10-07 10 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のために返されます。

[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を書くことができますので、私はしていない方法はあります:しかし、私はユニットテストクラスではなく、構成ファイルで定義されるように使用さPASSWORD_PRIVATE_KEY値がしたいです私のテストのための構成ファイルはどれですか?

+0

この問題とは異なることに注意してください。http://stackoverflow.com/q/6851816/1192381 –

+0

標準的な答えは、「静的に初期化された 'private static'フィールドを使用しないでください」 - リファクタ、' Password'クラスそこで、あなたはそれをモックアップできる協力者クラスから 'PASSWORD_PRIVATE_KEY'の値を取得します。この場合、 'ConfigFile'を非静的にすることが答えになるようです。 – millimoose

+2

一般的に言えば、「静的」とは、単体テストの敵です。 – 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など)。したがって、を手動で実装する必要はありません。

+0

ありがとうございます。私はこのアプローチをとるでしょうが、代わりに 'ConfigFile'クラスのモックを使用するので、テストのために' Password'クラスを変更する必要はありません。 –

1

No. プライベートフィールドにアクセスする方法はありません。

ユニットテストでは、通常、内部のものにアクセスしたいのですが、これはInternalsVisibleToを使用して行うことができます。しかし、それでもプライベートなメンバーはプライベートなままです。これらのフィールドにゲッターを定義することができます。

編集:少し煩雑な構文では、PrivateObjectsを使用してプライベートフィールドにアクセスできます。

+0

' _Accessor'ラッパーの使用内部クラスのプライベートフィールドへの書き込み権限があります。 1つのプロジェクトではテスト対象のアプリケーションを、もう1つのプロジェクトではユニットテストのクラスを持っています。 フィールドが 'プライベート'であるという問題はないと思いますが、 'static readonly'であり、テスト時に値が与えられているという事実です。 –

2

私は.NETのエキスパートではありませんので、これを塩の塊で取ってください。

単体テストの値の1つは、コードを再考する必要があることを示しています。テストが難しい場合は、書き直す必要があります。

Passwordにファイルの抽象化を挿入し、その抽象化の模擬実装を作成する方法を解説します(たとえば、MoqまたはRhino Mocksを使用)。

しかし、今のところ、ファイルを使用する方法はないと思います。代わりに別のファイルを見るようにテストする必要があります。

希望に役立ちます。

+0

"代わりに別のファイルを見るようにテストする必要があります。"ありがとうございました。それは私がやることだ。 'ConfigFile'のモックを持って、実際には設定ファイルから読み込まず、' Password'クラスが 'ReadByte()'を呼び出す前にプログラムで割り当てることができる値を返します。 –

関連する問題