[解決済み] テスト用のDBをシミュレートする方法(Java)
質問
私はJavaでプログラミングをしており、私のアプリケーションはDBを多く利用しています。したがって、私のDBの使用を簡単にテストできることが重要です。
DBのテストは何のためにあるのでしょうか?私にとっては、2つの簡単な要件を満たすものであるべきです。
- SQL 構文を検証する。
- より重要なのは、与えられた状況に応じて、データが正しく選択/更新/挿入されることを確認することです。
さて、それでは必要なのはDBだけのようですね。
でも実は、テストにDBを使うのはあまり難しいことではないので、使わない方がいいんです。
- 私の職場では、個人的なテスト DB を持つことはかなり不可能です。誰もがアクセスできる公開 DB を使用する必要があります。
- DBのテストは通常のテストよりも遅くなる傾向があります。遅いテストがあることは本当に理想的ではありません。
- DB のすべてのケースをシミュレートしようとすると、やや煩わしくなり、不可能にさえなります。各ケースについて、一定量の挿入/更新クエリを作成する必要があり、これは煩わしく、時間がかかります。
- テストにおける主な原則の1つは、テストしたコードとは異なる方法で機能をテストできるようにすることです。DBを使用するとき、通常、何かをする1つの方法があります、したがって、テストはコアコードとまったく同じです。
ですから、テストに関して言えば、私はDBが好きではないことがおわかりいただけると思います(もちろん、ある時点でこれに到達しなければなりませんが、私はむしろ、残りのテストメソッドを使用してほとんどのバグを見つけた後、私のテストの後半でこれに到達したいのです)。しかし、私は何を探しているのでしょうか?
私は、ファイルシステムまたは単なる仮想メモリを使用して、DB、モックDBをシミュレートする方法を探しています。おそらく、テストごとに、シミュレートされたテーブルと行、SQL 検証、およびその状態を監視するためのコード インターフェイスを備えた DB モックを (SQLを使用せずに) 簡単に構築できる Java ツール/パッケージがあると考えました。
この種のツールにお詳しいですか?
編集します。 回答ありがとうございました! 私はツールを求めていたのですが、あなたはまた、問題に関するいくつかのヒントを提供してくれました :) 私はあなたの提供をチェックアウトするのに時間がかかるので、あなたの答えが満足のいくものであったかどうか、今言うことはできません。
とにかく、私が探しているもののより良いビューはここにあります - その機能の1つがテーブルの行数を見つけることであるDBMonitorというクラスを想像してみてください。以下は、私がJUnitを使用してその機能をどのようにテストしたいかの想像上のコードです。
public class TestDBMonitor extends TestCase {
@Override
public void setUp() throws Exception {
MockConnection connection = new MockConnection();
this.tableName = "table1";
MockTable table = new MockTable(tableName);
String columnName = "column1";
ColumnType columnType = ColumnType.NUMBER;
int columnSize = 50;
MockColumn column = new MockColumn(columnName, columnType, columnSize);
table.addColumn(column);
for (int i = 0; i < 20; i++) {
HashMap<MockColumn, Object> fields = new HashMap<MockColumn, Object>();
fields.put(column, i);
table.addRow(fields);
}
this.connection = connection;
}
@Test
public void testGatherStatistics() throws Exception {
DBMonitor monitor = new DBMonitor(connection);
monitor.gatherStatistics();
assertEquals(((MockConnection) connection).getNumberOfRows(tableName),
monitor.getNumberOfRows(tableName));
}
String tableName;
Connection connection;
}
このコードが私のアイデアを理解するのに十分明確であることを望みます(構文エラーについては失礼します、私は私の愛するEclipseを使わずに手入力していました :P)。
ところで、私は部分的にORMを使用しており、私の生のSQLクエリは非常に単純であり、プラットフォームごとに異なるべきではありません。
どのように解決するのですか?
古い質問に対する新しい答えです(しかし、物事は少し前進しています)。
テスト(Java)のためにDBをシミュレートする方法は?
リポジトリをモックしてテストしないか、同じDBをテストに使ってsqlをテストします。そして、コネクションや結果セットなどの深いDBオブジェクトをモック/シミュレートすることは決してしないでください。
個人でテスト用DBを持つのはかなり無理があります。誰もがアクセスできるパブリックDBを使用する必要があります。
残念ながら、多くの企業がまだこのモデルを使用していますが、現在では ドッカー 商用製品では、テストには重要でないいくつかの制限(数GBのデータまでなど)があります。また、スキーマと構造はこのローカルデータベースで作成する必要があります。
<ブロッククオートDBのテストは通常のテストよりも遅くなる傾向があります。遅いテストがあるのは本当に理想的ではありません。
はい、DBテストは遅いですが、それほど遅くありません。私はいくつかの簡単な の計測を行いました。 を測定したところ、典型的なテストは5-50msでした。時間がかかるのはアプリケーションの起動です。
- まず、DIフレームワーク(springなど)は、アプリケーションの一部だけを実行する方法を提供します。データベースと非データベースのロジックをうまく分離してアプリケーションを書けば、テストの中で、次のことができます。 DB 部分のみを起動する
- 各dbは、耐久性を下げ、より速くするための多くのチューニングオプションを持っています。 Postgres の例
-
データベース全体をtmpfsに置くこともできます。
-
別の有用な戦略は、テストのグループを持ち、DBテストをデフォルトでオフにしておくことです(ビルドが本当に遅くなる場合)。この方法では、誰かが実際にDBで作業する場合、コマンドラインで追加のフラグを渡すかIDEを使用する必要があります(テストンググループとカスタムテストセレクタはこれに最適です)。
それぞれのケースについて、一定量の挿入/更新クエリを作成する必要があり、これは煩わしいし時間もかかる
時間がかかる」というのは前述したとおりですが、迷惑なのでしょうか?私は2つの方法を見ました。
-
通常、データセットはコードから分離されており、何キロバイト、何メガバイトもあります。
count(*)
は失敗します。いくつかのテストを削除しても、どの行がこのテストにのみ使用されたのか分からないので、それは大きくなるだけです。 - こうすることで、各テストは完全に独立し、読みやすく、推論しやすくなります。
テストにおける主な原則の1つは、テストされたコードとは異なる方法で機能をテストできるようにすることです。
主な原則は、ソフトウェアが特定の入力に応答して望ましい出力を生成するかどうかをチェックすることです。
dao.insert
を 542 回呼び出し、その後
dao.count
が542を返したら、それはあなたのソフトウェアが指定されたとおりに動作していることを意味します。もちろん、時にはコントラクトの代わりに実装をテストしたい場合もあり、その場合はdaoがデータベースの状態を変更したかどうかをチェックします。しかし、常にSQL AをSQL Bでテストします(insert vs select, sequence next_val vs returned valueなど)。
あなたを助けるかもしれない他のツール。
-
テストコンテナ を提供するのに役立ちます。 を提供するのに役立ちます。
-
dbunit - はテストの間にデータをきれいにするのに役立ちます
は短所です。
- スキーマとデータを作成し、維持するために多くの作業が必要です。
- 別の抽象化レイヤーのため、このツールでサポートされていないデータベース機能を突然使用したくなった場合、テストするのが難しいかもしれない。
-
テステージ - は、完全で、すぐに使えて、拡張可能なライフサイクルを提供することを意図しています(開示:私はクリエイターです)。
の短所です。
- 小規模なプロジェクトのみ無料
- 非常に若いプロジェクト
-
飛行場 または リキベース - これらは、テスト用にローカルのデータベースでスキーマとすべての構造を簡単に作成することを手助けしてくれます。
関連
-
unsigned char* から const jbyte* {aka const signed char*} への変換が無効です。
-
Java Runtime Environmentを継続するためのメモリが不足しています。
-
[解決済み] JavaでInputStreamを読み込んでStringに変換するにはどうすればよいですか?
-
[解決済み] JavaでNullPointerExceptionを回避する方法
-
[解決済み] JavaにおけるHashMapとHashtableの違いは何ですか?
-
[解決済み] Java Mapの各エントリを効率的に反復処理するには?
-
[解決済み] Javaでメモリーリークを発生させるにはどうしたらいいですか?
-
[解決済み] JavaでStringをintに変換するにはどうしたらいいですか?
-
[解決済み] プライベートメソッド、フィールド、インナークラスを持つクラスをテストするにはどうすればよいですか?
-
[解決済み】Android UserManager.isUserAGoat()の正しい使用例?)
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
javaの非静的メソッドを静的に参照することができない
-
ブートレイヤーの初期化中にエラーが発生しました java.lang.module.FindException: モジュールが見つかりません
-
が 'X-Frame-Options' を 'sameorigin' に設定したため、フレーム内に存在する。
-
無効なメソッド宣言
-
List list = new ArrayList(); Error: ArrayList は型に解決できません。
-
CertificateException: XXXに一致するサブジェクトの代替DNS名が見つかりません 解決策
-
Server Tomcat v9.0 Server at localhost の起動に失敗しました。
-
Java基礎 - マッピングとQ/A
-
switch case文のcaseの後の列挙定数は列挙型なし
-
Zipファイルの圧縮・解凍にantを使用する