10

おそらく私の検索では完全に不十分でしたが、他の非プライベート メソッドを呼び出す Java クラス/メソッドの単体テストの作成方法に関するドキュメントやディスカッションを見つけることができませんでした。一見、Mockito は、内部メソッド呼び出しのモックが必要なメソッドをテストするためにスパイを使用する必要がある場合、設計に問題がある可能性がある (真の OO ではない) という立場をとっています。これが常に正しいとは限りません。しかし、スパイを使用することがこれを達成する唯一の方法のようです. たとえば、プリミティブな機能を他のメソッドに依存するが、他のメソッドの結果に依存する機能、エラー処理、ログ、またはさまざまなブランチなどを追加で提供する「ラッパー」スタイルのメソッドを作成できないのはなぜでしょうか?

だから私の質問は2つあります:

  1. 他のメソッドを内部的に呼び出すメソッドを持つのは、コードの設計と実装が不十分ですか?
  2. モッキングフレームワークとしてMockitoを選択した場合、そのようなメソッドの単体テストを作成する際のベストプラクティスおよび/またはアプローチは何ですか? (それ自体が良い考えであると仮定して)

これは難しい要求かもしれませんが、私はそのアプローチとイデオロギーをすでに認識しているので、単に Mockito の言い回しやスパイに対するスタンスを再公開するだけでなく、回答することを決定した人を希望します. また、Powermockito も使用しました。私にとっての問題は、Mockito がこのフレームワークを開発したことであり、この必要性をサポートするために追加の回避策を作成する必要がありました。したがって、私が答えを求めている質問は、スパイが「悪い」ものであり、Powermockito が利用できない場合、他の非プライベート メソッドを呼び出すメソッドをどのように単体テストすることになっているのでしょうか?

4

4 に答える 4

7

他のメソッドを内部的に呼び出すメソッドを持つのは、コードの設計と実装が不十分ですか?

あまり。しかし、この状況では、他のメソッドを呼び出すメソッドは、他のメソッドがまだ個別にテストされていないかのようにテストする必要があります。つまり、パブリック メソッドが気付かないうちに他のメソッドの呼び出しを停止する状況からユーザーを保護します。

はい、(場合によっては) 大量のテスト コードが必要になります。これが要点だと思います。テストを作成する際の苦労は、これらのサブメソッドを別のクラスに抽出することを検討する良い手がかりになります。

これらのテストに耐えることができれば、サブメソッドはまだ抽出されていないと思います。

モッキングフレームワークとしてMockitoを選択した場合、そのようなメソッドの単体テストを作成する際のベストプラクティスおよび/またはアプローチは何ですか? (それ自体が良い考えであると仮定して)

私はそのようなことをします:

public class Blah {
    public int publicMethod() {
        return innerMethod();
    }

    int innerMethod() {
        return 0;
    }
}


public class BlahTest {
    @Test
    public void blah() throws Exception {
        Blah spy = spy(new Blah());
        doReturn(1).when(spy).innerMethod();

        assertThat(spy.publicMethod()).isEqualTo(1);
    }
}
于 2012-09-28T10:34:07.547 に答える
3

私にとって、この質問は結束の概念に強く関係しています。

私の答えは次のとおりです。

クラス内の他のメソッド (private) を呼び出すメソッド (public) を使用することは問題ありません。実際、私が良いコードと考えるのは非常によくあることです。ただし、これには注意点があります。クラスは依然として強力に結束している必要があります。私にとってそれは、クラスの「状態」を明確に定義する必要があり、クラスのメソッド (動作を考える) がクラスの状態を予測可能な方法で変更することに関与する必要があることを意味します。

これは、あなたがテストしようとしているものに当てはまりますか? そうでない場合は、2 つ (またはそれ以上) を見なければならないときに、1 つのクラスを見ている可能性があります。

テストしようとしているクラスの状態変数は何ですか?

これらの種類の質問への回答を検討した後、コードは、本来あるべきだと思う方法でテストするのがはるかに簡単になることに気付くかもしれません。

于 2013-07-22T23:23:46.773 に答える
2

下位レベルのメソッドを再度呼び出さないようにする必要がある(または必要な)場合は、それらをモックする代わりにスタブアウトすることができます。たとえば、メソッドAがBとCを呼び出す場合、次のように実行できます。

MyClass classUnderTest = new MyClass() {
    @Override
    public boolean B() {return true;}

    @Override
    public int C() {return 0;}
};
doOtherCommonSetUp(classUnderTest);
String result = classUnderTest.A("whatever");
assertEquals("whatIWant", result);

私はこれをレガシーコードでかなり使用しましたが、大規模なリファクタリングはソフトウェアバージョンの造船病に簡単につながる可能性があります。テストが難しいものを小さな方法に分離し、それをスタブします。

ただし、呼び出されるメソッドがかなり無害で、モックを必要としない場合は、メソッド内のすべてのパスをカバーしていることを心配せずに、メソッドを再度呼び出すようにします。

于 2012-09-27T17:25:13.510 に答える
2

本当の質問は次のとおりです。

本当に何をテストしたいのですか?

実際、答えは次のようになります。

外部の変化に対するオブジェクトの動作

つまり、オブジェクトを操作する方法に応じて、1 つのテストで可能なすべてのシナリオをテストする必要があります。このようにして、テストを提供するシナリオに応じて、期待どおりにクラスが反応することを確認できます。

他のメソッドを内部的に呼び出すメソッドを持つのは、コードの設計と実装が不十分ですか?

そうではありません、そして本当にそうではありません!パブリック メンバーから呼び出されるこれらのいわゆるプライベート メソッドは、ヘルパー メソッドです。ヘルパー メソッドを持つことはまったく正しいことです。

ヘルパー メソッドは、より複雑な動作を、クラス自体から再利用可能な小さなコードに分割するのに役立ちます。クラスのパブリックメンバーを介して、どのように動作し、それに応じて状態を返すかを知っているのは、それだけです。

ヘルパー メソッドを持つクラスを見ることはまれであり、通常、クラスが外部から反応してはならない内部動作を採用する必要があります。

モッキングフレームワークとしてMockitoを選択した場合、そのようなメソッドの単体テストを作成する際のベストプラクティスおよび/またはアプローチは何ですか? (それ自体が良い考えであると仮定して)

私の謙虚な意見では、これらの方法をテストしていません。それらは、パブリック メンバーの呼び出し時にオブジェクトから期待される状態を通じてパブリック メンバーがテストされるときにテストされます。たとえば、MVP パターンを使用してユーザー認証をテストする場合、すべてのプライベート メソッドをテストする必要はありません。プライベート メソッドは、テスト対象のオブジェクトに依存するオブジェクトから他のパブリック メソッドを呼び出す可能性があるためです。代わりに、ビューをテストします。

@TestFixture
public class TestView {
    @Test
    public void test() {
        // arrange
        string expected = "Invalid login or password";
        string login = "SomeLogin";
        string password = "SomePassword";

        // act
        viewUnderTest.Connect(login, password);
        string actual = viewUnderTest.getErrorMessage;

        // assert
        assertEqual(expected, actual);
    }
}

このテスト メソッドは、たとえば connectButton がクリックされた後のビューの予想される動作を記述します。プロパティに期待値が含まれていない場合はErrorMessage、ビューまたはプレゼンターが期待どおりに動作していないことを意味します。プレゼンターがビューのイベントをサブスクライブしたかどうかConnect、またはプレゼンターが正しいエラー メッセージを設定しているかどうかなどを確認できます。

実際には、プライベート メソッドで何が起こっているかをテストする必要はまったくありません。デバッグ時に調整して修正を加える必要があるためです。これらのヘルパー メソッド用に明示的に記述されています。

于 2014-03-20T15:43:14.247 に答える