2012-03-14 14 views
27

JUnit4とCoberturaで静的メソッドのみを使用してヘルパークラスをテストしています。テスト方法は簡単な作業であり、すでに完了しています。JUnit:静的メソッドのみを使用したヘルパークラスのテスト

しかし、coberturaは、クラスがどこにもインスタンス化されていないため、テストで完全にはカバーされないことを示しています。

私はこのクラスのインスタンス(ヘルパークラスです)を作成したくないので、まずはコンストラクタを隠すことです(ヘルパークラスの一般的なアプローチです)。

次に、coberturaは、空のプライベートコンストラクタがテストでカバーされていないと文句を言います。

このような状況で100%コードカバレッジを達成するソリューションはありますか?

トップレベルの管理(この場合)からコードカバレッジが必要なので、この特定のクラスの100%を取得することは非常に役に立ちます。あなたが明示的にプライベートコンストラクタを呼び出す場合を除き

答えて

27

いくつかの解決策があります。

  1. あなたはパブリックコンストラクタを追加し、テストからそれを呼び出すことができます。それは意味をなさないが、それはまた傷つけない(多く)。

  2. ダミーの静的インスタンスを作成します(プライベートコンストラクタはここで呼び出すことができます)。醜いですが、フィールドにあなたの意図を伝えるための名前を付けることができます(JUST_TO_SILENCE_COBERTURAはいい名前です)。

  3. ヘルパークラスをテストすることができます。これは本質的にデフォルトのコンストラクタを呼び出しますが、ヘルパークラスはfinalにはなりません。

特に、クラスがfinalになることができないため、最後のアプローチをお勧めします。コードのコンシューマが別のヘルパーメソッドを追加したい場合、既存のクラスを拡張して1つのハンドルを受け取り、すべてのヘルパーメソッドを取得できます。これは、意図を伝達するヘルパーメソッドのカップリング(これらは一緒に属している)を作成します - あなたが誤っヘルパークラスをインスタンス化するユーザーを防止したい場合は、ヘルパークラスがfinal

であれば不可能であり、それをabstractを作る代わりに使用して隠されたコンストラクタ。

+1

第3のアプローチは、私の意見では、コードに全く影響を与えない(テストのみ)という理由もあります。私はこのようにします。ご協力ありがとうございます。 –

2

あなたはそれらの行をカバーすることができません(不正なコードになります)。

7

すべてのケースで100%のカバレッジを取得していますが、これはできない場合もあります。もちろん、インスタンス化されないクラスがある場合、これらのコード行は実際にクラスに含まれているため、テストされませんので、Coberturaはこれを完全なテストカバレッジとして取得しません。

実際にプライベートコンストラクタを呼び出すことはありません(プライベートにすることでコンストラクタを隠したと仮定しています)ので、気にしません。テストは、あなたが期待しているものを得ることに関するものでなければならず、100%のカバレッジが良いと同意している間に、このような場合には役に立たない場合もあります。

100% Code Coverageもご覧ください。

+2

トップレベルの管理からコードカバレッジが必要な場合があります(この場合はそうです)、このクラスの100%を取得するのには非常に役に立ちます。そしてはい - 私はこのアプローチのばかげたことを認識しています。しかし、記事のリンクありがとうございました。 –

27

コードカバレッジを100%達成する必要がある場合 - そのメリットは他の場所で議論することができます:) - テストでリフレクションを使用して達成できます。習慣として、静的専用のユーティリティクラスを実装するときには、クラスのインスタンスを作成できないように私用のコンストラクタを追加します。たとえば:

/** 
* Constructs a new MyUtilities. 
* @throws InstantiationException 
*/ 
private MyUtilities() throws InstantiationException 
{ 
    throw new InstantiationException("Instances of this type are forbidden."); 
} 

次に、あなたのテストでは、次のようになります。

@Test 
public void Test_Constructor_Throws_Exception() throws IllegalAccessException, InstantiationException { 
    final Class<?> cls = MyUtilties.class; 
    final Constructor<?> c = cls.getDeclaredConstructors()[0]; 
    c.setAccessible(true); 

    Throwable targetException = null; 
    try { 
     c.newInstance((Object[])null); 
    } catch (InvocationTargetException ite) { 
     targetException = ite.getTargetException(); 
    } 

    assertNotNull(targetException); 
    assertEquals(targetException.getClass(), InstantiationException.class); 
} 

は基本的に、何をここでやっていることは、名前でクラスを取得し、そのクラス型のコンストラクタを見つけ、設定されましたpublicに(setAccessible呼び出し)、引数のないコンストラクタを呼び出し、スローされたターゲット例外がInstantiationExceptionであることを確認します。

あなたの言ったように、100%のコードカバレッジ要件はここでは痛みですが、それはあなたの手の中にあるように聞こえます。私は実際に私のコードで上記のようなアプローチを使用しましたが、テストの観点からは有益ではありませんでした。むしろ、それは私が前に知っていたよりも反射についてもう少し学ぶのを助けました:)

+1

+1素敵なハック:-) –

+0

+1、賢い解決策! – JW8

+0

なぜキャッチブロックに「戻る」があるのですか?テストは常にtrueを返します。 ;) –

関連する問題