5

CheckブロッキングwaitForCondition()メソッドを持つ非常に単純なクラスがあります。このメソッドはブロックしています。このメソッドの単体テストをいくつか作成したいと思います。まず、条件が満たされたときにメソッドが戻る必要があります。第二に、メソッドは中断されたときに戻る必要があります。

内部的に、Checkクラスには がありArrayBlockingQueue、そのメソッドを呼び出します。そのtake()ため、私のテストは、条件のロジックを正しく (あるべきように) コーディングしたかどうかについてです。アプリケーションでは、クラスのデータはメソッドCheckを介して別のスレッドから供給されます。InputDataこのInputDataメソッドは、受信データに対してロジックを実行し、条件が満たされたときにダミー オブジェクトを ArrayBlockingQueue に配置します。waitForCondition()これにより、返されるはずです。

したがって、最初に考えたのはInputData、モックを作成してテストし、条件が満たされたときにダミー オブジェクトがキューに追加されることを確認できるということです。これには、クラスの設計を変更する必要があります。これは、キューがプライベート データ メンバーであるためです (プライベート データをモックできる場合を除く)。条件が満たされたときにキューに直接追加する代わりに、InputDataモックできる何かを呼び出す必要があります。

しかし、それが正しく機能しwaitForCondition()ていることを考えると、メソッド自体をチェックするという問題があります。InputDataそれは本当に単純なコードです:

try {
        myArrayBlockingQueue.take();
        return true;
    } catch (InterruptedException ex) {
        return false;
    }

だから私はそれが想像上の問題に値するかどうか疑問に思っています: で別のスレッドを作成しCheck、その を呼び出し、waitForCondition()完了時に何かを返すテスト。おそらく、Executor サービスを使用しています。あいまいな部分は、を同期する方法assertTrue(...)です。非同期テストに関するこの記事を見つけました。これでうまくいくようです。

質問の要約:

  1. ロジックをテストするためにデザインを変更する必要がInputData()ありますか。
  2. waitForCondition()がテストされている限り、テストを除外する必要がInputData()ありますか?
  3. それとも、実行する必要があること (やや複雑な単体テスト) を実行して、waitForCondition()直接テストする方がよいでしょうか?
4

3 に答える 3

3

Check クラスのコンストラクターに ArrayBlockingQueue のインスタンスを挿入すると、テストの途中で適切な値を挿入できます。

次に、タイムアウトを指定して単体テストを実行し、100 ミリ秒以内に返されない場合は失敗します。

于 2012-07-11T15:15:40.370 に答える
1

素敵なリンクをありがとう!私はいくつかの同様の問題に直面しましたが、おそらくそのリンクは私が行ったよりも良い方法です. (この質問に対する他の回答も知りたいです-それは良い質問です)

実際のコードを (少なくとも一時的に)変更してもかまわない場合(はい、これは通常の単体テストの方法ではありません!)、私が「エラー挿入」と呼んだことを行うことができます。

私の実装では、プロパティ (またはマップ) から読み取るクラスを作成して、特定の一意のポイントで「面白いことをする」ようにします。たとえば、あなたのプロパティは言うかもしれません

myClass.myMethod.blockingQueueTake = interrupt:
myClass.myLongCalculation = throw: java.lang.ArithmeticException(Failed to converge)

コードで、テスト行を追加します。たとえば、 の直前にqueue.take()

TestSimulator.doCommand("myClass.myMethod.blockingQueueTake");

利点は、すべてが実際のコードで行われることであり、非常に複雑になる可能性があるモックではありません。(私の場合、SW は古く、単体テスト用に作成/設計されていないため、モックを作成するのは非常に困難でした) 欠点は、後でコードを削除またはコメントアウトする必要があることです。したがって、これは継続的インテグレーション タイプの単体テストではなく、1 回限りの非常に深刻な現実のデバッグです。ですから、理想とはほど遠いことは認めますが、たくさんのバグが見つかりました!

于 2012-07-11T15:06:56.610 に答える
0

「テスト ランナー」クラスを使用して、アサートをループで実行することもできます。ループは、try/catch でアサートを実行します。例外ハンドラーは、タイムアウトになるまでアサートを再度実行しようとします。最近、この手法に関するブログ記事を書きました。この例は groovy で書かれていますが、概念は Java に簡単に適応できるはずです。

http://www.greenmoonsoftware.com/2013/08/asynchronous-functional-testing/

于 2013-08-15T03:02:55.103 に答える