web-dev-qa-db-ja.com

JUnitテストプライベート変数?

私はJUnitで直接作業したことのないクラスを単体テストするタスクを割り当てられており、パッケージ内のコードを変更することは固く禁じられています。これは通常、問題になりません。ユニットテストのほとんどは機能と入出力の一貫性のためだけであり、ルーチンを実行して戻り値を確認するだけで実行できます。

ただし、クラス内のプライベート変数を確認したり、プライベート変数を直接編集して内部動作を確認したりする必要がある場合があります。元のソースパッケージのコードを実際に変更せずに単体テストの目的で、JUnitを介して、またはその他の方法でこれらにアクセスする方法はありますか?そうでない場合、単体テスターがコーダーと同じ人物ではない現実の世界で、プログラマーはこの問題をどのように処理しますか?

63
donnyton

うん、リフレクションを使ってプライベート変数にアクセスできます。完全に良い考えではありません。

これをチェックしてください:

http://en.wikibooks.org/wiki/Java_Programming/Reflection/Accessing_Private_Features_with_Reflection

28
Alfredo Osorio

まず第一に、あなたは現在悪い立場にあります-あなたが元々作成しなかったコードのためのテストを書くタスクを持っていて、変更なしで-悪夢です!上司と話して説明してください。「テスト可能」にせずにコードをテストすることはできません。コードをテスト可能にするには、通常、いくつかの重要な変更を行います。

プライベート変数について。実際にそれを行うべきではありません。プライベート変数をテストすることは、現在の設計に問題があることの最初の兆候です。プライベート変数は実装の一部であるため、テストでは実装の詳細ではなく動作に注目する必要があります。

プライベートフィールドは、いくつかのゲッターを使用してパブリックアクセスに公開される場合があります。私はそれを行いますが、可能な限り避けるようにします(「テストに使用」などのコメントにマークを付けます)。

コードを変更する可能性がないので、プライベート変数をチェックする可能性はありません(Reflectionハッキングなどではなく、本当の可能性を意味します)。

50

反射 例:

public class PrivateObject {

  private String privateString = null;

  public PrivateObject(String privateString) {
    this.privateString = privateString;
  }
}
PrivateObject privateObject = new PrivateObject("The Private Value");

Field privateStringField = PrivateObject.class.
            getDeclaredField("privateString");

privateStringField.setAccessible(true);

String fieldValue = (String) privateStringField.get(privateObject);
System.out.println("fieldValue = " + fieldValue);
17
bpgergo

明白なことを述べる危険性にもかかわらず:単体テストでは、オブジェクトの正しい動作をテストする必要があります。これは、パブリックインターフェイスの観点から定義されます。オブジェクトがこのタスクをどのように達成するかに興味はありません-これは実装の詳細であり、外部には見えません。これが、OOが発明された理由の1つです。その実装の詳細は隠されています。したがって、プライベートメンバーをテストする意味はありません。オブジェクトのパブリックインターフェイスを使用してテストできないコードの場合、このコードは実際には呼び出されないため、テストできません。

3
MKK

この問題を解決する記事を以下に示します(具体的にはテストが含まれます)。

http://onjava.com/pub/a/onjava/2003/11/12/reflection.html

1
Joe0

テストクラスを別のフォルダーに作成し、ビルドパスに追加すると、

次に、パッケージを正しく使用して名前空間を設定することにより、テストクラスをテスト対象クラスの内部クラスにすることができます。これにより、プライベートフィールドとメソッドにアクセスできます。

ただし、リリースビルドのビルドパスからフォルダーを削除することを忘れないでください。

0
Andrew p

プライベートフィールドに対してテストする必要がある特別なケースコードを見つけたかどうかはわかりません。しかし、私の経験では、プライベートなものをテストする必要はありません-常に公開しています。たぶん、プライベートをテストする必要があるコードの例を挙げることができますか?

0
ThomasArdal