web-dev-qa-db-ja.com

JUnit:静的メソッドのみを使用したヘルパークラスのテスト

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

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

このクラス(ヘルパークラス)のインスタンスを作成したくないので、最初の解決策はコンストラクターを非表示にすることです(これは一般的にヘルパークラスに適したアプローチです)。

次に、coberturaは、空のプライベートコンストラクターがテストの対象外であると不平を言います。

そのような状況で100%のコードカバレッジを達成するための解決策はありますか?

トップレベルの管理者(この場合)にはコードカバレッジが必要であるため、この特定のクラスの100%を取得することは非常に役立ちます。

32

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

  1. パブリックコンストラクターを追加して、テストから呼び出すことができます。それは意味がありませんが、害を及ぼすこともありません。

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

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

特に、クラスをfinalにすることはできないため、最後のアプローチをお勧めします。コードのコンシューマーが別のヘルパーメソッドを追加する場合は、既存のクラスを拡張し、1つのハンドルを受け取ってすべてのヘルパーメソッドにアクセスできます。これは、意図を伝えるヘルパーメソッドの結合を作成します(これらは一緒に属します)。これは、ヘルパークラスがfinalの場合は不可能です

ユーザーが誤ってヘルパークラスをインスタンス化しないようにする場合は、非表示のコンストラクターを使用する代わりに、ヘルパークラスをabstractにします。

31
Aaron Digulla

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);
}

基本的に、ここで行うことは、名前でクラスを取得し、そのクラス型のコンストラクタを見つけ、それをパブリックに設定し(setAccessible呼び出し)、引数なしでコンストラクタを呼び出し、次に、スローされるターゲット例外はInstantiationExceptionです。

とにかく、あなたが言ったように、ここでの100%のコードカバレッジ要件はちょっと面倒ですが、手に負えないように聞こえるので、それについてあなたができることはほとんどありません。私は実際に自分のコードで上記と同様のアプローチを使用しましたが、それは有益であることがわかりましたが、テストの観点からではありません。むしろ、それは私が以前に知っていたよりも反射についてもう少し学ぶのに役立ちました:)

29
matt

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

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

100%コードカバレッジ もご覧ください。

7
manub

番号。

プライベートコンストラクターを明示的に呼び出さない限り(これは悪いコードです)、これらの行をカバーすることはできません。

2
oers