私はJUnitでいくつかの統合テストを書いています。ここで何が起こるかというと、すべてのテストを続けて(個別にではなく)実行すると、データベースに保持されているデータは常に変更され、テストの実行中に予期しないデータ(前のテストによって挿入された)が検出されます。
DbUnitを使用することを考えていましたが、実行のたびに自動インクリメントインデックスがリセットされるかどうか疑問に思います(テストでは永続化されたエンティティのIDもチェックされるため)。
ありがとう
M。
私はJUnitでいくつかの統合テストを書いています。ここで何が起こるかというと、すべてのテストを続けて(個別にではなく)実行すると、データベースに保持されているデータは常に変更され、テストの実行中に予期しないデータ(前のテストによって挿入された)が検出されます。
DbUnitを使用することを考えていましたが、実行のたびに自動インクリメントインデックスがリセットされるかどうか疑問に思います(テストでは永続化されたエンティティのIDもチェックされるため)。
ありがとう
M。
テストを実行する前にデータベースを既知の状態にすることをお勧めします。DBUnitはそれに必要なすべてを提供します。ただし、自動インクリメントされた列に依存せず、DBUnitデータセットにも配置してください。長所:失敗したテストを実行した後、データベースの状態を手動で確認できます。短所:データセットを設定して維持する必要があります。
もう1つのアプローチは、トランザクション内で各テストメソッドを実行することです(実行の最後にトランザクションをロールバックします)。長所:データは(データベース内で)セットアップと保守が簡単です。短所:失敗したテストを修正するのはあまり便利ではありません。
単一のテストを実行するか、該当する場合はテストのグループを単一のトランザクションとして実行し、最後にロールバックすることができます。(テスト自体が複数のトランザクションで構成されていて、データベースがネストされたトランザクションまたはセーブポイントをサポートしていない場合、これは難しいかもしれません。)
または、テスト データベースをスクリプトで作成します。DbUnit は、 LiquiBase、dbmaintain、dbmigrateなどの他のデータベース ジェネレーターと同様に、ここで役立ちます。その後、データベース全体を削除し、テストまたはテスト グループごとに再作成できます。このアプローチの有用性は、テスト データセットが大きくなり、オーバーヘッドが増加するにつれて減少します。
最後のオプションは、生成された ID にテストを依存させないことです。生成された値に依存すると脆弱なテストが作成されるためです。生成された ID をテストすると便利なので、いくつかのテストでこれらの値をテストしますが、すべてのテストで Id をテストする価値があるかどうかはわかりません。
編集:OPは、休止状態を使用してスキーマを再作成することについて尋ねました。これは、テストごとに新しい SessionFactory を作成し、SessionFactory のビルド時に「hibernate.hbm2ddl.auto」を「true」に設定することで調整できます。drop-create の有効性が低下していることに言及しますが、これはこのケースにも当てはまります。
テストで id 値に依存するのは良くありません。自動インクリメントはデータベース固有のものであるからです。したがって、ID をチェックすることは決してありません。そうする場合、テストはエンティティが実際の例ではない特定の ID 値で満たされていることに依存します。テストは、自動インクリメント ID から独立している必要があります。
基本的に、この問題は 2 つの方法で解決できます。
DB 関連のテストをトランザクション内にラップします。テストの前にトランザクションを開始します。テスト実行が終了したら、トランザクションを中止します。常にトランザクションを中止します。この方法では、テストで行われた変更は保持されません。
DBUnit などを使用して DB 操作関連のクラスをモックし、DB にデータが送信されないようにし、クラスが DB 操作が行われたかのように結果を返すようにします。
テストの実行時に DB にアクセスする場合は、アプローチ 1 をお勧めします。