web-dev-qa-db-ja.com

ユニットテストとSpringとの統合テスト

私はSpringMVCプロジェクトに取り組んでおり、ソースツリーのさまざまなコンポーネントすべての単体テストを行っています。

たとえば、コントローラーHomeControllerがあり、それにLoginServiceを注入する必要がある場合、ユニットテストHomeControllerTestでは、オブジェクトを通常どおりにインスタンス化します(外部春の)そしてプロパティを注入します:

protected void setUp() throws Exception {
    super.setUp();
    //...
    controller = new HomeController();
    controller.setLoginService( new SimpleLoginService() );
    //...
}

これは、各コンポーネントを分離されたユニットとしてテストするのに最適です-プロジェクトに数十のクラスがあることを除いて、クラスを作成して成功したユニットテストを作成した後、SpringMVCコンテキストファイルを更新するのを忘れ続けています。デプロイされたアプリケーションでの実際の配線。プロジェクトをTomcatにデプロイするときに、コンテキストファイルを更新するのを忘れて、配線されていないBeanから多数のNullPointerを見つけたことがわかりました。

だから、ここに私の質問があります:

  1. これは私の最初のSpringプロジェクトです-私が行ったように個々のBeanの単体テストを作成し、次にテストの2番目のスイート(統合テスト)を作成して、すべてが実際のアプリケーションコンテキストで期待どおりに機能することをテストするのは正常ですか?これについて確立されたベストプラクティスはありますか?

  2. さらに、単体テストを統合テストからどのように分離しますか?すべてのソースコードはsrcにあり、単体テストはtestにあります-統合テストケース用の2番目のテストフォルダー(test-integrationなど)が必要ですか?

これは私の最初の春のプロジェクトなので、他の人が通常この種のことをどのように行うのか興味があります-そして、車輪の再発明ではなく、コミュニティの他の人に尋ねます。

38
matt b

ベストプラクティスであるとは言えませんが、これが過去に行ったことです。

ユニットテスト:

  • 重要なBean(つまり、Spring関連のBeanのほとんど)の単体テストを作成します
  • 実用的な場合(つまり、常にではないにしてもほとんど)、注入されたサービスにモックを使用します。
  • プロジェクトのtestディレクトリで、これらのテストに標準の命名規則を使用します。クラス名の接頭辞または接尾辞としてTestまたはTestCaseを使用することは、広く行われているようです。

統合テスト:

  • 統合テストクラスで使用するためにAbstractIntegrationTestCaseSpringを設定するWebApplicationContextを作成します。
  • testディレクトリでの統合テストには命名規則を使用してください。これらのテストの接頭辞または接尾辞としてIntTestまたはIntegrationTestを使用しました。

3つのAnttestターゲットを設定します。

  1. test-all(または名前を付けたいもの):ユニットテストと統合テストを実行します
  2. test:ユニットテストを実行します(ユニットテストの最も一般的な使用法はtestのようです。
  3. test-integration:統合テストを実行します。

前述のように、プロジェクトに適した命名規則を使用できます。

ユニットを統合テストから別のディレクトリに分離することに関しては、開発者とそのツールがそれらを見つけて実行できる限り、それは重要ではないと思います簡単に。

例として、Springで作業した最後のJavaプロジェクトは、同じtestディレクトリにある統合テストと単体テストで、上記とまったく同じものを使用しました。Grailsプロジェクト、一方、一般的なテストディレクトリの下に単体テストディレクトリと統合テストディレクトリを明示的に分離します。

32
Ken Gentle

いくつかの孤立点:

はい、これはSpringテストへの一般的なアプローチです。前者がSpringコンテキストをロードしない、個別の単体テストと統合テストです。

単体テストの場合は、モックを作成して、テストが1つの分離されたモジュールに焦点を合わせていることを確認することを検討してください。

テストが大量の依存関係で配線されている場合、それらは実際には単体テストではありません。これらは、依存性注入ではなく新しいものを使用して依存性を配線する統合テストです。本番アプリケーションでSpringを使用すると、時間の無駄と重複した労力が発生します。

Springコンテキストを表示するための基本的な統合テストが役立ちます。

@requiredアノテーションは、Spring配線で必要な依存関係を確実にキャッチするのに役立つ場合があります。

たぶん、Mavenを調べて、ユニットと統合テストをバインドするための明示的なフェーズを提供します。 MavenはSpringコミュニティで非常に広く使用されています。

6

@ Component、@ Controller、@ Service、および@RepositoryですべてのBeanに注釈を付ける純粋な注釈付きレジームに切り替えると、春の面倒な複式簿記の多くがなくなります。注入する必要のある属性に@Autowiredを追加するだけです。

スプリングリファレンスマニュアルのセクション3.11を参照してください。 http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-annotation-config

関連する注記として、KenGが説明する除算ユニット/インテグラトリオンテストを使用しています。私の最近の体制では、テストの3番目の「クラス」である「ComponentTests」も導入しました。これらは完全なスプリング配線で実行されますが、ワイヤードスタブの実装で実行されます(スプリングでコンポーネントスキャンフィルターと注釈を使用)。

これを行った理由は、一部の「サービス」レイヤーでは、Beanを手動でワイヤリングするための膨大な量の手動でコーディングされたワイヤリングロジックと、場合によってはばかげた量のモックオブジェクトが発生するためです。 5ラインのテストに対して100ラインの配線は珍しいことではありません。コンポーネントテストはこの問題を軽減します。

4
krosenvold

InitializingBeanインターフェース(メソッド「afterPropertiesSet」を実装)を使用するか、Beanのinitメソッドを指定します。 Beanにinitメソッドを追加することを覚えておく必要がないため、InitializingBeanは通常簡単です。

AfterPropertiesSetを使用して、すべてがnull以外として挿入されるようにします。nullの場合は、例外をスローします。

2
MetroidFan2002

Webアプリケーションの統合テストを作成したら、それらを別のディレクトリに配置しました。これらはjUnitまたはTestNGを使用して構築され、ユーザーであるかのようにWebページにアクセスする Selenium のようなものを使用してテスト対象のシステムと対話します。サイクルは次のようになります。コンパイル、単体テストの実行、Webアプリのビルド、実行中のサーバーへのデプロイ、テストの実行、アプリのアンデプロイ、結果のレポート。アイデアは、システム全体をテストすることです。

0
sblundy

単体テストと統合テストの違いは、単体テストは必ずしもコンテキストをロードするわけではなく、作成したコードに焦点を合わせていることです。依存する呼び出しをモックすることで、例外の有無にかかわらず、高速に失敗します。ただし、統合テストの場合は、コンテキストをロードして、実際のシナリオのようにエンドツーエンドのテストを実行します。

0
Ali

統合テストとは別に単体テストを実行することに関しては、後者をすべて統合テストディレクトリに配置し、 this のようなアプローチを使用してIDE/Antを使用して実行します。私のために働きます。

0
Paul McKenzie