6

のインターフェースが定義されていると仮定します

interface Foo {
  int getBaz();
  void doBar();
}

さらに、doBar が呼び出されるたびに baz がインクリメントされることが契約に記載されているとします。(わかりました、これは不自然なコードですが、ここに固執してください)

ここで、Foo の実装者がすべての契約条件を満たしていることを確認できるように、単体テストを提供したいと思います。

class FooTest {
  protected Foo fooImpl;

  @Test
  public void int testBazIncrement()
  {
    int b = fooImpl getBaz();
    fooImpl.doBar();
    Assert.assertEquals( b+1, fooImpl.getBaz();
  }
}

Foo の実装者がテストを利用できるようにするためのベスト プラクティスは何ですか? FooTest を呼び出し、Foo インスタンスを構築するために Foo または FooFactory を提供するためのメカニズムが必要であるように私には思えます。さらに、多くのテスト (大きなインターフェイスを考えてください) がある場合、それらすべてのテストを 1 つの FooTest クラスに入れたいと考えています。

このようなテストを実装するためのベスト プラクティスはありますか?

4

5 に答える 5

2

これは、依存性注入の教科書的な例です。Spring を DI コンテナーとして使用する場合は、fooImpl

@Inject
protected Foo fooImpl;

テストには で注釈を付ける必要があり@RunWith(SpringJUnit4ClassRunner.class)、実装で Spring を構成するのはインターフェイス プロバイダー次第です。

DI コンテナーがなければ、すべてのテストを含む抽象テスト クラスと、実装オブジェクトを提供する抽象メソッドを作成するだけです。

protected abstract Foo createFoo();

テストをサブクラス化し、抽象メソッドを実装するのは、実装プロバイダー次第です。

class FooImplTest extends FooTestSuper {

@Override
protected Foo createFoo() {
    return new FooImpl();
}

複数のテストがある場合は、JUnit の@Suiteアノテーションを検討してください。Spring テストランナーと互換性があります。

于 2013-01-08T10:40:08.413 に答える
0

たとえば、単体テストInterfaceImplATestInterfaceImplBTestなどから呼び出されるInterfaceTesterを持たないのはなぜですか?

例えば

@Test
public void testSerialisation()
{
  MyObject a = new MyObject();

  ...

  serialisationTester.testSimpleRoundTrip(a);

  serialisationTester.testEdgeCases(a);

  ... 
}
于 2013-01-08T15:47:10.143 に答える
0

オブジェクトをインスタンス化する場所に testDataFactory を実装するか、GSon を使用してオブジェクトを作成できます (個人的には、GSon が好きです。明確で高速です。数時間で習得できます)。テストの実装については、単一のテストではなく、より多くのテストを作成することをお勧めします。このようにして、単体テストを独立させることができ、閉じた構造で問題を分離することができます。

ソナー

Sonar は、コードの解析を行うのに非常に役立つツールです。アプリケーションがどのようにテストされているかをソナーフロントエンドから確認できます。

ソナー単体テスト

ご覧のとおり、Sonar はコードがテストされている場所とテストされていない場所を表示できます

于 2013-01-08T08:35:11.047 に答える
-1

以下は、適格な単体テストの作成方法に関する私の考えの一部です。

まず、実装者クラスを完全にテストするようにしてください。つまり、そのすべてのメソッドを UT でカバーする必要があります。これを行うと、コードをリファクタリングする必要があるときに多くの時間を節約できます。あなたの場合、それは次のようになります:

class FooTest {
    protected Foo fooImpl;

    @Test
    public void testGetBaz() {
    ...
    }

    @Test
    public void testDoBar() {
    ...
    }

}

クラスの内部状態を確認する必要があることがわかりますが、UT は一種のホワイト ボックス テストであるため、何も問題はありません。

次に、すべてのメソッドを個別にテストし、相互に依存しないようにする必要があります。私の意見では、上記のコードについては、機能テストまたは統合テスト以上のもののように見えますが、それも必要です。

第三に、スプリングやその他のコンテナーを使用してターゲット オブジェクトを組み立てるのは良い習慣ではないと思います。これにより、特に実行するテストの負荷がある場合に、テストの実行が比較的遅くなります。また、クラスは本質的に pojo である必要があり、ターゲット オブジェクトが非常に複雑な場合は、テスト クラスの別のメソッドでアセンブルを完了することができます。

第 4 に、あるクラスの親インターフェイスが非常に大きい場合は、テスト メソッドをいくつかのグループに分割する必要があります。ここに詳細があります。

于 2013-01-08T14:12:28.607 に答える