web-dev-qa-db-ja.com

静的メソッドの単体テスト

ここでは、decryptメソッドのテストケースを記述しようとしています。

    private static Codec codec;

    static {
        try {
            codec = new Codec(encryptionType, encryptionKey, false, true, false);
        } catch (CodecException e) {
            throw new RuntimeException("Codec initialisation failed", e);
        }
    }


    public static String decrypt(final String toDecrypt) throws CodecException {
        String decrypted = codec.decryptFromBase64(toDecrypt);
        if (decrypted.endsWith(":")) {
            decrypted = decrypted.substring(0, decrypted.length() - 1);
        }
        return decrypted;
    }

テストケース:

    @Mock
    private Codec codec;
    @Test
    public void test_decrypt_Success() throws CodecException {
        when(codec.decryptFromBase64(TestConstants.toDecrypt)).thenReturn(TestConstants.decrypted);
        assertEquals(DocumentUtils.decrypt(TestConstants.toDecrypt), TestConstants.decrypted);
    }

これは静的メソッドなので、テストスイートにクラスのインスタンスを挿入して、そのコーデックをモックすることはできません。上記のコードは、想定どおりにアサート時にコーデックライブラリからエラーをスローします。

このような静的メソッドをテストするためのアプローチは何ですか?それとも私はこれのためのテストをまったく書くべきではありませんか?

4
tanvi

Javaでは、静的メソッドは依存関係を設定するようには設計されていません。
したがって、依存関係をモックに切り替えるのは実際には自然ではありません。
次のようなフィールドにstaticセッターを提供できます:

_private static Codec codec;
public static void setCodec(Codec codec){
   this.codec = codec;
}
_

そして、setCodec(...)でモックを設定することもできますが...

ただし、忘れないでください。コードをリファクタリングしてすべての静的要素を削除し、コーデックを設定するコンストラクタを導入します。

_private Codec codec;
public MyClassUnderTest(Codec codec){
   this.codec codec;
}
_

IOCは、テスト対象のクラスをシングルトンにして、依存関係の挿入を容易にするのに役立ちます。
あなたのケースで不可能である場合、Java 5列挙は、少なくともシングルトンの問題を解決するのに役立ちます。

3
davidxxx

同じことを達成するための多くの異なるショートカット方法があります(コメントや他の回答で指摘されています)が、特に長期的にはすべてが良いとは限りません。

Decrypt機能を実装するシングルトンクラスを作成することをお勧めします。したがって、複数のインスタンスを作成する必要はありません。また、実際に復号化するための静的メソッドも必要ありません。また、コーデックを1回以上簡単に注入できます(複数のタイプのコーデックはないので、コメントに従ってください。ただし、その場合、機能はそれに応じて変更されます)。

詳細情報: 静的メソッドの代わりにシングルトンを使用する理由

静的を注意深く使用する必要がある理由の参考:- 静的変数が悪と見なされるのはなぜですか?

2
Ankur Chrungoo

それらの場合の私の経験では、@ Beforeメソッドですべてのインスタンスを準備するだけです。

private Codec codec;

@Before
public void setup() throws CodecException {
  codec = new Codec(encryptionType, encryptionKey, false, true, false);
}
0
Juan Ramos