3028

JUnit を使用して、内部プライベート メソッド、フィールド、またはネストされたクラスを持つクラスをテストするにはどうすればよいですか?

テストを実行できるようにするためだけにメソッドのアクセス修飾子を変更するのは良くないようです。

4

58 に答える 58

1774

アップデート:

約 10 年後、おそらくプライベート メソッドまたはアクセスできないメンバーをテストする最良の方法は、 Manifoldフレームワーク@Jailbreakから経由することです。

@Jailbreak Foo foo = new Foo();
// Direct, *type-safe* access to *all* foo's members
foo.privateMethod(x, y, z);
foo.privateField = value;

このようにして、コードは型安全で読みやすいままになります。設計上の妥協はなく、テストのために方法やフィールドを過度に露出することもありません。

レガシーJavaアプリケーションがあり、メソッドの可視性を変更できない場合、プライベート メソッドをテストする最善の方法は、リフレクションを使用することです。

内部的にはヘルパーを使用してprivateと変数を取得/設定し、とメソッドprivate staticを呼び出します。次のパターンでは、プライベート メソッドとフィールドに関連するほとんどすべてのことを実行できます。もちろん、リフレクションによって変数を変更することはできません。privateprivate staticprivate static final

Method method = TargetClass.getDeclaredMethod(methodName, argClasses);
method.setAccessible(true);
return method.invoke(targetObject, argObjects);

フィールドの場合:

Field field = TargetClass.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(object, value);

注:
1.メソッドTargetClass.getDeclaredMethod(methodName, argClasses)を調べることができますprivate。についても同様です getDeclaredField
2.setAccessible(true)プライベートで遊ぶには必要です。

于 2008-08-29T16:35:11.560 に答える
745

プライベート メソッドをテストする最良の方法は、別のパブリック メソッドを使用することです。これができない場合は、次のいずれかの条件が当てはまります。

  1. プライベート メソッドはデッド コードです
  2. テストしているクラスの近くにデザインの匂いがあります
  3. テストしようとしているメソッドはプライベートであってはなりません
于 2008-08-29T16:14:19.943 に答える
360

クラスにプライベートメソッドがあり、プライベートメソッドを直接テストする必要があると感じる場合、それはコードの臭いです。クラスが複雑すぎます。

このような問題に対処するための私の通常のアプローチは、興味深いビットを含む新しいクラスを引き出すことです。多くの場合、このメソッドとそれが相互作用するフィールド、およびおそらく別のメソッドまたは2つを新しいクラスに抽出できます。

新しいクラスはこれらのメソッドを「public」として公開するため、単体テストでアクセスできます。新しいクラスと古いクラスはどちらも元のクラスよりも単純になりました。これは私にとって素晴らしいことです(物事を単純に保つ必要があります。そうしないと迷子になります!)。

私は人々が彼らの脳を使わずにクラスを作成することを示唆していないことに注意してください!ここでのポイントは、ユニットテストの力を使用して、優れた新しいクラスを見つけるのに役立てることです。

于 2008-09-09T14:43:05.230 に答える
231

この記事: Testing Private Methods with JUnit and SuiteRunner (Bill Venners) から、基本的に 4 つのオプションがあります。

  1. プライベート メソッドをテストしないでください。
  2. メソッドにパッケージへのアクセス権を付与します。
  3. ネストされたテスト クラスを使用します。
  4. 反射を使用します。
于 2008-08-29T16:16:20.047 に答える
143

通常、ユニット テストは、クラスまたはユニットのパブリック インターフェイスを実行することを目的としています。したがって、プライベート メソッドは、明示的にテストする必要のない実装の詳細です。

于 2008-08-29T16:14:54.637 に答える
74

プライベートメソッドをテストしたい場所の2つの例:

  1. 復号化ルーチン-テストのためだけに誰にも見えないようにしたいのですが、そうでなければ、誰でも復号化に使用できます。SecurityManagerただし、これらはコードに固有であり、複雑であり、常に機能する必要があります(明らかな例外は、これを防ぐように構成されていない場合、ほとんどの場合、プライベートメソッドを表示するために使用できるリフレクションです)。
  2. コミュニティで使用するためのSDKを作成します。ここでは、これは(私のアプリケーションの内部だけでなく)全世界が見る可能性のあるコードであるため、publicはまったく異なる意味を持ちます。SDKユーザーにコードを見せたくない場合は、コードをプライベートメソッドに入れます。これは、SDKプログラミングの仕組みとしてだけでなく、コードの臭いとは見なされません。しかしもちろん、私はまだプライベートメソッドをテストする必要があり、それらは私のSDKの機能が実際に存在する場所です。

「契約」のみをテストするという考えを理解しています。しかし、実際にコードをテストしないことを主張できる人はいないと思います。マイレージは異なる場合があります。

したがって、私のトレードオフには、セキュリティとSDKを損なうのではなく、JUnitをリフレクションで複雑にすることが含まれます。

于 2010-07-05T06:10:13.873 に答える
64

プライベート メソッドはパブリック メソッドによって呼び出されるため、パブリック メソッドへの入力は、それらのパブリック メソッドによって呼び出されるプライベート メソッドもテストする必要があります。public メソッドが失敗した場合、それは private メソッドの失敗である可能性があります。

于 2008-08-29T16:15:30.127 に答える
44

Spring Frameworkでは、このメソッドを使用してプライベート メソッドをテストできます。

ReflectionTestUtils.invokeMethod()

例えば:

ReflectionTestUtils.invokeMethod(TestClazz, "createTest", "input data");
于 2015-06-24T08:01:08.710 に答える
43

私が使用した別のアプローチは、private メソッドをパッケージ化する private または protected に変更し、Google Guava ライブラリの@VisibleForTestingアノテーションでそれを補完することです。

これは、このメソッドを使用するすべての人に注意を促し、パッケージ内であっても直接アクセスしないようにします。また、テストクラスは物理的に同じパッケージにある必要はありませんが、テストフォルダーの下の同じパッケージにある必要があります。

たとえば、テストするメソッドが にある場合、src/main/java/mypackage/MyClass.javaテスト コールは に配置する必要がありますsrc/test/java/mypackage/MyClassTest.java。そうすれば、テスト クラスのテスト メソッドにアクセスできます。

于 2016-03-20T15:53:03.747 に答える
39

大規模で風変わりなクラスを使用してレガシー コードをテストするには、現在作成中の 1 つのプライベート (またはパブリック) メソッドをテストできると非常に役立ちます

私はjunitx.util.PrivateAccessor -package for Java を使用しています。プライベート メソッドとプライベート フィールドにアクセスするための便利なワンライナーがたくさんあります。

import junitx.util.PrivateAccessor;

PrivateAccessor.setField(myObjectReference, "myCrucialButHardToReachPrivateField", myNewValue);
PrivateAccessor.invoke(myObjectReference, "privateMethodName", java.lang.Class[] parameterTypes, java.lang.Object[] args);
于 2011-01-12T10:27:21.030 に答える
33

Java用のリフレクションを使用してCemCatikkasのソリューションを試したので、彼はここで説明したよりもエレガントなソリューションだったと言わざるを得ません。ただし、リフレクションを使用する代わりの方法を探していて、テストしているソースにアクセスできる場合は、これはオプションです。

特にテスト駆動開発では、コードを作成する前に小さなテストを設計したい場合に、クラスのプライベートメソッドをテストすることにはメリットがあります。

プライベートメンバーとメソッドにアクセスできるテストを作成すると、パブリックメソッドのみにアクセスするだけでは特にターゲットを絞ることが難しいコードの領域をテストできます。パブリックメソッドに複数のステップが含まれる場合、それはいくつかのプライベートメソッドで構成され、個別にテストできます。

利点:

  • より細かい粒度でテストできます

短所:

  • テストコードはソースコードと同じファイルに存在する必要があり、これは保守がより困難になる可能性があります
  • .class出力ファイルと同様に、それらはソースコードで宣言されたものと同じパッケージ内にとどまる必要があります

ただし、継続的テストでこのメソッドが必要な場合は、プライベートメソッドを抽出する必要があることを示している可能性があります。これは、従来のパブリックメソッドでテストできます。

これがどのように機能するかの複雑な例を次に示します。

// Import statements and package declarations

public class ClassToTest
{
    private int decrement(int toDecrement) {
        toDecrement--;
        return toDecrement;
    }

    // Constructor and the rest of the class

    public static class StaticInnerTest extends TestCase
    {
        public StaticInnerTest(){
            super();
        }

        public void testDecrement(){
            int number = 10;
            ClassToTest toTest= new ClassToTest();
            int decremented = toTest.decrement(number);
            assertEquals(9, decremented);
        }

        public static void main(String[] args) {
            junit.textui.TestRunner.run(StaticInnerTest.class);
        }
    }
}

内部クラスはにコンパイルされClassToTest$StaticInnerTestます。

参照:Javaヒント106:楽しみと利益のための静的内部クラス

于 2008-09-01T20:58:47.270 に答える
28

他の人が言ったように...プライベートメソッドを直接テストしないでください。ここにいくつかの考えがあります:

  1. すべてのメソッドを小さくし、焦点を絞ってください (テストしやすく、問題を見つけやすくします)。
  2. コード カバレッジ ツールを使用します。Coberturaが好きです(新しいバージョンが出たようです!)

単体テストでコード カバレッジを実行します。メソッドが完全にテストされていないことがわかった場合は、テストに追加してカバレッジを上げてください。100% のコード カバレッジを目指しますが、おそらく達成できないことを認識してください。

于 2009-02-14T18:53:03.637 に答える
28

プライベート メソッドは、パブリック メソッドによって消費されます。そうでなければ、それらはデッド コードです。そのため、パブリック メソッドをテストして、パブリック メソッドの期待される結果をアサートし、それによってプライベート メソッドを消費します。

プライベート メソッドのテストは、パブリック メソッドで単体テストを実行する前に、デバッグによってテストする必要があります。

また、テスト駆動開発を使用してデバッグし、すべてのアサーションが満たされるまで単体テストをデバッグすることもできます。

個人的には、TDD を使用してクラスを作成する方がよいと考えています。パブリック メソッド スタブを作成し、事前に定義されたすべてのアサーションを使用して単体テストを生成します。これにより、メソッドの期待される結果は、コーディングする前に決定されます。このようにして、単体テストのアサーションを結果に適合させるという間違った道をたどることはありません。すべての単体テストに合格すると、クラスは堅牢になり、要件を満たします。

于 2013-12-02T21:12:53.650 に答える
27

Spring を使用している場合、ReflectionTestUtilsは、最小限の労力でここで役立ついくつかの便利なツールを提供します。たとえば、望ましくないパブリック セッターを追加せずにプライベート メンバーにモックを設定するには、次のようにします。

ReflectionTestUtils.setField(theClass, "theUnsettableField", theMockObject);
于 2014-11-10T23:36:00.430 に答える
26

変更したくない、または変更できない既存のコードをテストしようとしている場合は、リフレクションが適しています。

クラスの設計がまだ柔軟で、個別にテストしたい複雑なプライベート メソッドがある場合は、それを別のクラスに取り出して、そのクラスを個別にテストすることをお勧めします。これは、元のクラスのパブリック インターフェイスを変更する必要はありません。ヘルパー クラスのインスタンスを内部的に作成し、ヘルパー メソッドを呼び出すことができます。

ヘルパー メソッドから発生する難しいエラー条件をテストする場合は、さらに一歩進んでください。ヘルパー クラスからインターフェイスを抽出し、パブリック ゲッターとセッターを元のクラスに追加してヘルパー クラスを挿入し (そのインターフェイスを介して使用)、元のクラスにヘルパー クラスのモック バージョンを挿入して、元のクラスがどのように機能するかをテストします。ヘルパーからの例外に応答します。このアプローチは、ヘルパー クラスをテストせずに元のクラスをテストする場合にも役立ちます。

于 2008-09-05T16:39:45.170 に答える
20

プライベート メソッドをテストすると、内部実装を変更するたびにクライアント コード (この場合はテスト) が壊れるため、クラスのカプセル化が壊れます。

したがって、プライベート メソッドをテストしないでください。

于 2008-10-10T06:44:02.160 に答える
18

コードを変更できないレガシー アプリケーションのプライベート メソッドをテストする場合、Java のオプションの 1 つはjMockit です。これにより、オブジェクトがクラスに対してプライベートであってもオブジェクトのモックを作成できます。

于 2008-09-09T03:50:56.967 に答える
18

JUnit.org の FAQ ページからの回答:

しかし、もしあなたがしなければならないなら...

JDK 1.3 以降を使用している場合は、リフレクションを使用して、PrivilegedAccessorを使用してアクセス制御メカニズムを無効にすることができます。詳しい使い方はこちらの記事をご覧ください。

JDK 1.6 以降を使用していて、テストに @Test のアノテーションを付ける場合、Dp4jを使用してテスト メソッドにリフレクションを挿入できます。使用方法の詳細については、このテスト スクリプトを参照してください。

PS 私はDp4jの主な貢献者です。助けが必要な場合はに尋ねてください。:)

于 2011-02-22T19:41:11.420 に答える
17

JUnit を使用している場合は、junit-addons をご覧ください。Java セキュリティ モデルを無視し、プライベート メソッドと属性にアクセスする機能があります。

于 2008-09-11T22:20:28.407 に答える
17

私はプライベートメソッドをテストしない傾向があります。狂気があります。個人的には、公開されたインターフェイス (および保護された内部メソッドを含む) のみをテストする必要があると思います。

于 2008-08-29T16:23:45.893 に答える
15

コードを少しリファクタリングすることをお勧めします。コードをテストするためだけに、リフレクションやその他の種類のものを使用することを考え始めなければならない場合、コードに問題が発生しています。

あなたはさまざまな種類の問題について言及しました。プライベートフィールドから始めましょう。プライベート フィールドの場合は、新しいコンストラクターを追加し、それにフィールドを注入します。これの代わりに:

public class ClassToTest {

    private final String first = "first";
    private final List<String> second = new ArrayList<>();
    ...
}

私はこれを使用していたでしょう:

public class ClassToTest {

    private final String first;
    private final List<String> second;

    public ClassToTest() {
        this("first", new ArrayList<>());
    }

    public ClassToTest(final String first, final List<String> second) {
        this.first = first;
        this.second = second;
    }
    ...
}

これは、一部のレガシー コードでも問題になりません。古いコードは空のコンストラクターを使用します。私に尋ねると、リファクタリングされたコードはきれいに見え、リフレクションなしで必要な値をテストに挿入できるようになります。

次に、プライベート メソッドについて説明します。私の個人的な経験では、テストのためにプライベート メソッドをスタブする必要がある場合、そのメソッドはそのクラスでは何の関係もありません。その場合の一般的なパターンは、インターフェイス内でラップCallableし、コンストラクターでもそのインターフェイスを渡すことです (複数のコンストラクターのトリックを使用)。

public ClassToTest() {
    this(...);
}

public ClassToTest(final Callable<T> privateMethodLogic) {
    this.privateMethodLogic = privateMethodLogic;
}

私が書いたもののほとんどは、依存性注入パターンのように見えます。私の個人的な経験では、テスト中には非常に便利です。この種のコードはよりクリーンで、保守が容易になると思います。ネストされたクラスについても同じことが言えます。ネストされたクラスに重いロジックが含まれている場合は、それをパッケージ プライベート クラスとして移動し、それを必要とするクラスに注入した方がよいでしょう。

レガシ コードのリファクタリングと保守の際に使用した他のデザイン パターンもいくつかありますが、それはすべて、テストするコードのケースによって異なります。リフレクションを使用することはほとんど問題ではありませんが、十分にテストされたエンタープライズ アプリケーションがあり、すべての展開の前にテストが実行されると、すべてが非常に遅くなります (面倒で、私はそのようなことは好きではありません)。

セッター注入もありますが、使用はお勧めしません。コンストラクターを使い続けて、本当に必要なときにすべてを初期化し、必要な依存関係を注入する可能性を残したほうがよいでしょう。

于 2016-08-29T21:10:59.453 に答える
12

上記の多くの人が示唆しているように、パブリック インターフェイスを介してテストすることをお勧めします。

これを行う場合は、コード カバレッジ ツール (Emma など) を使用して、プライベート メソッドが実際にテストから実行されているかどうかを確認することをお勧めします。

于 2008-09-10T07:48:42.957 に答える
12

今日、プライベート メソッドとフィールドのテストに役立つ Java ライブラリをプッシュしました。Android を念頭に置いて設計されていますが、実際にはどの Java プロジェクトにも使用できます。

プライベート メソッド、フィールド、またはコンストラクターを含むコードを取得した場合は、BoundBoxを使用できます。それはまさにあなたが探していることをします。以下は、Android アクティビティの 2 つのプライベート フィールドにアクセスしてテストするテストの例です。

@UiThreadTest
public void testCompute() {

    // Given
    boundBoxOfMainActivity = new BoundBoxOfMainActivity(getActivity());

    // When
    boundBoxOfMainActivity.boundBox_getButtonMain().performClick();

    // Then
    assertEquals("42", boundBoxOfMainActivity.boundBox_getTextViewMain().getText());
}

BoundBoxを使用すると、プライベート/保護されたフィールド、メソッド、およびコンストラクターを簡単にテストできます。継承によって隠されているものにもアクセスできます。実際、BoundBox はカプセル化を破ります。リフレクションを通じてすべてにアクセスできますが、コンパイル時にすべてがチェックされます。

一部のレガシー コードをテストするのに理想的です。慎重に使用してください。;)

https://github.com/stephanenicolas/boundbox

于 2013-09-17T20:23:50.100 に答える
10

最初に、次の質問を投げかけます。プライベート メンバーに分離テストが必要なのはなぜですか? それらはそれほど複雑で、一般公開されていない場所でのテストが必要なほど複雑な動作を提供しますか? これは単体テストであり、「コード行」テストではありません。小さなことを気にしないでください。

それらが非常に大きく、これらのプライベート メンバーがそれぞれ複雑な「ユニット」になるほど大きい場合は、このクラスからそのようなプライベート メンバーをリファクタリングすることを検討してください。

リファクタリングが不適切または実行不可能な場合、戦略パターンを使用して、単体テスト時にこれらのプライベート メンバー関数/メンバー クラスへのアクセスを置き換えることができますか? 単体テストでは、この戦略は追加の検証を提供しますが、リリース ビルドでは単純なパススルーになります。

于 2008-09-18T09:29:50.913 に答える
9

私は最近この問題を抱えており、Picklockと呼ばれる小さなツールを作成しました。これは、Java リフレクション API を明示的に使用する際の問題を回避します。2 つの例を次に示します。

メソッドの呼び出し (例: private void method(String s)Java リフレクションによる)

Method method = targetClass.getDeclaredMethod("method", String.class);
method.setAccessible(true);
return method.invoke(targetObject, "mystring");

メソッドの呼び出し、例えばprivate void method(String s)- Picklock による

interface Accessible {
  void method(String s);
}

...
Accessible a = ObjectAccess.unlock(targetObject).features(Accessible.class);
a.method("mystring");

フィールドの設定、例えばprivate BigInteger amount;- Java リフレクションによる

Field field = targetClass.getDeclaredField("amount");
field.setAccessible(true);
field.set(object, BigInteger.valueOf(42));

フィールドの設定、例えばprivate BigInteger amount;- Picklock による

interface Accessible {
  void setAmount(BigInteger amount);
}

...
Accessible a = ObjectAccess.unlock(targetObject).features(Accessible.class);
a.setAmount(BigInteger.valueOf(42));
于 2015-05-07T06:02:44.853 に答える
6

Javaの場合は、リフレクションを使用します。テストのためだけに、宣言されたメソッドのパッケージへのアクセスを変更するという考えが気に入らないからです。ただし、通常はパブリック メソッドをテストするだけで、プライベート メソッドが正しく機能していることも確認できます。

リフレクションを使用して所有者クラスの外部からプライベート メソッドを取得することはできません。プライベート修飾子はリフレクションにも影響します。

本当じゃない。Cem Catikkas's answerで述べたように、あなたは間違いなくそうすることができます。

于 2008-08-29T16:30:03.570 に答える
5

リフレクションの Java アクセス制限をオフにして、private が無意味になるようにすることができます。

setAccessible(true)呼び出しはそれを行います。

唯一の制限は、ClassLoader がそれを禁止する可能性があることです。

Javaでこれを行う方法については、単体テスト用の Java アクセス保護の破壊(Ross Burton) を参照してください。

于 2009-02-14T18:54:45.287 に答える
3

これが良い手法かどうかはわかりませんが、プライベート メソッドを単体テストするために次のパターンを開発しました。

テストしたいメソッドの可視性を変更せず、追加のメソッドを追加します。代わりに、テストするすべてのプライベート メソッドにパブリック メソッドを追加しています。この追加のメソッドを呼び出しTest-Port、接頭辞 で示しますt_。このTest-Portメソッドは、対応するプライベート メソッドにアクセスするだけです。

さらに、ブール値フラグをメソッドに追加して、外部からTest-Portメソッドを介してプライベート メソッドへのアクセスを許可するかどうかを決定しTest-Portます。このフラグは、アプリケーションの他のグローバル設定などを配置する静的クラスでグローバルに設定されます。したがって、対応する単体テストなど、1 つの場所でプライベート メソッドへのアクセスのオンとオフを切り替えることができます。

于 2011-11-15T16:22:36.120 に答える
3

ExpectedException を使用する場合の @Cem Catikka のコメントへの簡単な追加:

予想される例外は InvocationTargetException にラップされることに注意してください。そのため、例外に到達するには、受け取った InvocationTargetException の原因をスローする必要があります。(BizService でプライベート メソッド validateRequest() をテストする) のようなもの:

@Rule
public ExpectedException thrown = ExpectedException.none();

@Autowired(required = true)
private BizService svc;


@Test
public void testValidateRequest() throws Exception {

    thrown.expect(BizException.class);
    thrown.expectMessage(expectMessage);

    BizRequest request = /* Mock it, read from source - file, etc. */;
    validateRequest(request);
}

private void validateRequest(BizRequest request) throws Exception {
    Method method = svc.getClass().getDeclaredMethod("validateRequest", BizRequest.class);
    method.setAccessible(true);
    try {
        method.invoke(svc, request);
    }
    catch (InvocationTargetException e) {
        throw ((BizException)e.getCause());
    }
 }
于 2016-06-03T15:47:49.310 に答える
2

C# では を使用できましたがSystem.Reflection、Java ではわかりません。とにかくこれに答えたいという衝動を感じますが、「プライベートメソッドを単体テストする必要があると感じた」場合は、他に何か問題があると思います...

私は自分のアーキテクチャをもう一度新鮮な目で見ることを真剣に検討します...

于 2009-02-14T19:11:01.863 に答える
2

テスト クラスがテスト対象のクラスと同じパッケージに含まれている場合はどうなるでしょうか。

ただし、もちろん、ソースコードとテストクラスのsrc&は別のディレクトリにあります。そして、あなたのクラスパスにいさせてください。classestest/srctest/classesclassestest/classes

于 2009-06-24T13:49:43.653 に答える
2

PowerMock.Whitebox私が見た中で最良のオプションですが、そのソースコードを読むと、リフレクションでプライベートフィールドを読み取るので、答えがあると思います:

  • PowerMock を使用してプライベートな内部状態 (フィールド) をテストするか、別の独立性を導入するオーバーヘッドなしでリフレクションのみをテストします。
  • プライベートメソッドの場合:実際、この質問自体に対する賛成票、および膨大な数のコメントと回答は、それが非常に同時発生的で物議を醸すトピックであることを示しており、あらゆる状況に合わせて明確な回答を与えることはできません. 契約のみをテストする必要があることは理解していますが、考慮すべき補償範囲もあります。実際、コントラクトをテストするだけで、クラスが 100% エラーの影響を受けなくなるとは思えません。プライベート メソッドは、データが定義されているクラスでデータを処理するため、他のクラスには関係がないため、単純に公開してテスト可能にすることはできません。私はそれらをテストしないようにしますが、あなたがしなければならないときは、ただそれを試して、ここにあるすべての答えを忘れてください. あなたは自分の状況と制限を、インターネットの他の誰よりもよく知っています。コードを制御できる場合は、それを使用してください。考慮しながら、しかし過度に考えずに。

しばらくして再考したとき、私はまだこれが真実であると信じていますが、より良いアプローチを見つけました.

まず、Powermock.Whiteboxまだまだ使えます。

また、MockitoWhiteboxは v2 の後に非表示になり (私が見つけることができる最新バージョンWhiteboxは ですtestImplementation 'org.mockito:mockito-core:1.10.19')、常にorg.mockito.internalパッケージの一部であり、将来的に重大な変更が発生する可能性があります (この投稿を参照)。なので、今は使わないようにしています。

Gradle/Maven プロジェクトでは、プライベート メソッドまたはフィールドを定義する場合、リフレクション以外にそれらにアクセスする方法がないため、最初の部分はそのままです。ただし、可視性を「パッケージ プライベート」に変更すると、パッケージ内の同じ構造に従うテストtestがそれらにアクセスできるようになります。mainこれは、testパッケージ内で同じ階層を作成することが推奨されるもう 1 つの重要な理由でもあります。したがって、本番コードとテストを制御できる場合は、そのprivateアクセス修飾子を削除することが最適なオプションになる可能性があります。これは、比較的大きな影響を与えないためです。そして、これにより、テストとプライベート メソッドのスパイが可能になります。

@Autowired
private SomeService service; // with a package private method "doSomething()"

@Test
void shouldReturnTrueDoSomething() {
    assertThat(doSomething(input), is(true)); // package private method testing
}

@Test
void shouldReturnTrueWhenServiceThrowsException() {
    SomeService spy = Mockito.spy(service); // spying real object
    doThrow(new AppException()).when(spy).doSomething(input); // spy package private method
    ...

}

内部フィールドに関して言えば、Spring にはReflectionUtils.setField().

最後に、問題自体を回避できる場合もあります。満たすべきカバレッジ要件がある場合は、これらのプライベート メソッドを内部の静的クラスに移動し、Jacoco でこのクラスを無視することができます。Jacoco gradle タスクで内部クラスを無視する方法を見つけました。別の質問

于 2019-05-12T14:27:33.637 に答える
1

JML has a spec_public comment annotation syntax that allows you to specify a method as public during tests:

private /*@ spec_public @*/ int methodName(){
...
}

This syntax is discussed at http://www.eecs.ucf.edu/~leavens/JML/jmlrefman/jmlrefman_2.html#SEC12. There also exists a program that translates JML specifications into JUnit tests. I'm not sure how well that works or what its capabilities are, but it doesn't appear to be necessary since JML is a viable testing framework on its own.

于 2013-03-04T00:07:43.577 に答える
0

私はパブリック インターフェイスのみをテストしますが、特定のプライベート メソッドを保護することで知られているため、それらを完全にモック アウトするか、単体テストの目的に固有の追加の手順を追加できます。一般的なケースは、単体テストから設定できるフラグをフックして、特定のメソッドが故意に例外を発生させ、フォールト パスをテストできるようにすることです。例外をトリガーするコードは、保護されたメソッドのオーバーライドされた実装のテスト パスにのみ存在します。

ただし、私はこの必要性を最小限に抑え、混乱を避けるために常に正確な理由を文書化しています.

于 2011-04-28T15:01:47.560 に答える
0

Groovy にはバグ/機能があり、これを使用して、プライベート メソッドをパブリック メソッドであるかのように呼び出すことができます。したがって、プロジェクトで Groovy を使用できる場合は、リフレクションの代わりに使用できるオプションです。例については、このページをご覧ください。

于 2012-01-02T20:12:54.590 に答える