ResultSetの扱いについて
解決したいこと
javaのjunitテストにおけるテストデータについて、DBのプライマリキーに値が入っていないものをSELECTするテストケースを作成しようと思いMockを使おうと思っています。
この時、Mockの返す値としてResultSet型を指定したいのですが、中身の値設定方法が分かりません。
値の設定方法を教えてください。
自分で試したこと
そもそも、ResultSetに値を入れる方法が分からないため何も試せていません。
javaのjunitテストにおけるテストデータについて、DBのプライマリキーに値が入っていないものをSELECTするテストケースを作成しようと思いMockを使おうと思っています。
この時、Mockの返す値としてResultSet型を指定したいのですが、中身の値設定方法が分かりません。
値の設定方法を教えてください。
そもそも、ResultSetに値を入れる方法が分からないため何も試せていません。
それは、何をテストすることを目的としているのでしょうか?
(以下、あくまで私見で、プロジェクトにより事情は異なると思います。)
java.sql.PreparedStatement や java.sql.ResultSet は所謂データアクセス層の処理であり、一般的にはORマッパーの担当領域となります。
ORマッパー系のライブラリを使わず自前のコードで書くにしても、データアクセス層は内部ではDBアクセス・クエリ文の決定や発行・データ取得・ビジネスロジックで定義した型への変換を一手に引き受け、外部から見ると「ビジネスロジックで定義される型で引数を渡すと、ビジネスロジックの型で返すようなメソッドを持つモジュール」のように振舞うべきです。(※ビジネスロジックの型とは、独自のクラス定義+一般的なListやStringやintなどの組み合わせを意図しています)
ビジネスロジック層をテストしたい場合は、データアクセス層ごと全部モックで置き換えます(ResultSetを扱う処理はテストしません)。
データアクセス層をテストしたい場合は、DBUnitのようなライブラリを用いて、DBへの操作全体をテストします(いわゆるslow testになってしまいますが、本当にDB操作をテストできるために『テスト用モックの品質』を考える必要がありません)。
java.sql.ResultSet クラスはDBへの問い合わせ実行結果を Java の値へ変換するクラスで、DBと直接の結びつきがそこそこ強いです。具体的なDB内のデータの状態や目的のクエリやそのパラメータによって様々な結果を取りうるため、ここをモックに置き換えるのは割と面倒だったりします。
ですので、私がアプリケーションのテストを書く場合は、ResultSet をモックで置き換えるようなテストは作成しません。
前述のデータアクセス層とビジネスロジック層の違いを意識するなら、ResultSet をモックに置き換えるテストは「層の中身のテスト」=結びつきの強い箇所を無理に分断するようなテストになるからです。
もちろんデータアクセス層(ORマッパー系)のライブラリそのものを開発・テストする場合なんかは ResultSet の仕様や挙動を理解するためにもたくさんテストを書くとは思いますが。
繰り返しになりますが一般的なアプリケーション実装の場合は、ビジネスロジック層のテストか、データアクセス層のテストかで、手法自体を切り替えることをお勧めします。