2012-12-29 3 views
39

クラスには、静的メソッドの束が含まれている場合は、誤って誰もが、このクラスのインスタンスを初期化していないことを確認するために、私はプライベートコンストラクタを作っ:Javaアプリケーションでプライベートコンストラクタをテストする方法は?

private Utils() { 
} 

今..これは試験することができますか、コンストラクタが見えないとすれば?これはまったくカバーされたテストですか?あなたもそのことはできませんすることができ、しかし

Constructor<Util> c = Utils.class.getDeclaredConstructor(); 
c.setAccessible(true); 
Utils u = c.newInstance(); // Hello sailor 

private Utils() { 
    throw new UnsupportedOperationException(); 
} 

をコンストラクタで例外をスローすることによって反射を利用し

+1

Reflection APIを使用 – MrSmith42

+0

どうすればよいですか?あなたは一例がありますか? – JAM

+2

あなたはしません。プライベートコンストラクタを使用してメソッドをテストします。 –

答えて

62

は、あなたがプライベートコンストラクタを呼び出すことができますすべての試行を防ぎます。

public final class Utils { 
    private Utils() { 
     throw new UnsupportedOperationException(); 
    } 
} 
+7

+1。例外についての優秀な点! – JAM

+1

ニース。また、例外が追加された場合、実際にユニットテストを行う理由があるかもしれません。 – msandiford

+3

UnsupportedOperationExceptionがIllegalStateExceptionよりも適切であることがわかりました。 –

6
@Test 
public// 
void privateConstructorTest() throws Exception { 
    final Constructor<?>[] constructors = Utils.class.getDeclaredConstructors(); 
    // check that all constructors are 'private': 
    for (final Constructor<?> constructor : constructors) { 
     Assert.assertTrue(Modifier.isPrivate(constructor.getModifiers())); 
    }   
    // call the private constructor: 
    constructors[0].setAccessible(true); 
    constructors[0].newInstance((Object[]) null); 
} 
+0

私のutilsクラスのテストカバレッジを100%に増やすために使用します – MrSmith42

+1

これはとてもクールです!ありがとうございます – JAM

+2

@ MrSmith42 100%に近いテストカバレッジを取得すること自体は物事ではありません。テストカバレッジはメトリックです。そして、実際の結果を達成するのではなく、メトリックを改善することだけを意図したアクションは、メトリックを値下げします。結局のところ、すべてのコードをすべてのメソッドを実行するテストでカバーすることはできますが、結果を検証することはできません。だから、プライベートなコンストラクタをテストすることは、そうする強い理由がある場合に限り、直接呼び出すことで意味があるかもしれません。 (可能であれば間接的にテストするほうが良いです - ファクトリメソッドなどを呼び出すことで)。 とにかく、必要に応じてそれを行う方法を知っているといいです:-) –

19

テスト、常にコードの意図.. :)例えば


私もクラス自体final、単に「理由」を作りたい場合のポイント非公開のコンストラクタは見えないので、テストする必要があるのはこの事実だけです。

APIを使用して、コンストラクタをクエリし、プライベート属性が設定されていることを検証します。あなたがオブジェクトの構築のための適切なテストをしたい場合は、あなたが構築されたオブジェクトを取得することができますパブリックAPIをテストする必要があります

@Test() 
public void testPrivateConstructors() { 
    final Constructor<?>[] constructors = Utils.class.getDeclaredConstructors(); 
    for (Constructor<?> constructor : constructors) { 
     assertTrue(Modifier.isPrivate(constructor.getModifiers())); 
    } 
} 

私はこのような何かをするだろう。これは、前述のAPIが存在する必要がある理由です。オブジェクトを適切に構築して、それをテストする必要があるからです。:)

+0

素晴らしいアイデア。コードカバレッジツールがあまりにも悪いと、テストしたことが分かりません。 –

+0

これを行うライブラリについてはhttps://github.com/trajano/commons-testingを参照し、ユーティリティクラスをテストしてください。 –

4

プライベートコンストラクタを使用している場合は、非公開のコードの非公開メソッドから呼び出されます。だからあなたはそのメソッドをテストし、あなたのコンストラクタはカバーされます。メソッドごとにテストすることに宗教的な美徳はありません。あなたは機能を探していますが、より優れたブランチカバレッジレベルを探しています。それを使用するコードパスを通してコンストラクタを実行するだけで、それを得ることができます。

コードパスが複雑でテストが難しい場合は、おそらくリファクタリングする必要があります。

5

誤って誰もが、このクラスのインスタンス

を初期化していないことを確認するには通常、私は何をすべきか、デフォルトのパッケージの可視性に民間からのメソッド/コンストラクタを変更することです。私はテストクラスに同じパッケージを使用しています。そのため、メソッド/コンストラクタは外部からでなくてもアクセス可能です。デフォルトの空のコンストラクタから

  1. スローにUnsupportedOperationException(「このクラスをインスタンス化しないでください!」):あなたができるクラスをインスタンス化しないようにポリシーを適用するために

  2. class abstract:静的メソッドのみを含む場合は、静的メソッドを呼び出すことはできますが、サブクラス化しない限りインスタンス化することはできません。

または1 + 2の両方を適用すると、テストでターゲットクラスと同じパッケージを共有する場合でも、コンストラクタをサブクラス化して実行できます。 これはまさに「エラープルーフ」であるはずです。悪意のあるコーダーはいつもあなたのようなコンストラクタで例外を追加した場合の回避策:)

3

があります:テストクラスでconstructor.newInstance()の呼び出しではなく、あなたのUnsupportedOperationExceptionInvocationTargetExceptionをスローします

private Utils() { 
    throw new UnsupportedOperationException(); 
} 

が、目的の例外はスローされた例外に含まれます。
の例外をアサートする場合は、例外が発生すると、呼び出し例外が捕捉された後で呼び出し例外の対象をスローする可能性があります。例えば
、あなたがこれを行うことがJUnitの4を使用して:

@Test(expected = UnsupportedOperationException.class) 
public void utilityClassTest() throws NoSuchMethodException, IllegalAccessException, InstantiationException { 
    final Constructor<Utils> constructor = Utils.class.getDeclaredConstructor(); 
    constructor.setAccessible(true); 
    try { 
     constructor.newInstance(); 
    } catch (InvocationTargetException e) { 
     throw (UnsupportedOperationException) e.getTargetException(); 
    } 
} 
-1

にはありません。コンストラクタはprivateです。それだけで十分です。 Javaはそのプライバシーを強制します。

プラットフォームをテストしないでください。

+0

他の方法ではアクセスできないコードをテストする実際的な使用例は、誰もそのクラスをもう一度見ないように、100%テストカバレッジを達成することです。カバレッジが95%に止まっている場合、多くの開発者がこの問題に何度も繰り返し衝突する理由を理解しようとするかもしれません。 また、Javaはプライバシーを守ります。 :) – thisismydesign

関連する問題