データベースに接続し、1つ以上のクエリを実行して、結果を処理するコードの単体テストを作成したいと思います。 (実際にデータベースを使用せずに)
ここで別の開発者は、xml構成ファイルに基づいて対応するオブジェクトを返す独自のDataSource、Connection、Statement、PreparedStatement、およびResultSet実装を作成しました。 (偽のデータソースを使用し、それが返す結果セットに対してテストを実行することもできます)。
ここで車輪を再発明しますか?このようなものはユニットテスト用にすでに存在しますか? jdbcコードをテストする他の/より良い方法はありますか?
DBUnit を [〜#〜] hsqldb [〜#〜] と組み合わせて使用すると、たとえばCSVファイルから初期データを読み取ることができます。
いくつかのオプションがあります:
これらのテストがデータベースが利用可能な場合にのみ実行されるように、これらのテストを構成可能にすることが必要かつ有用な場合があります。これは、たとえばビルドプロパティ。
私は次の組み合わせを使用したい:
DBUnitとHSQLDBを使用するだけで、かなり遠くまで到達できます。 Unitilsは、データベースの状態を管理およびリセットするためのコードの最後のマイルを提供します。また、データベーススキーマの変更を管理する優れた方法を提供し、特定のRBDMS(Oracle、DB2、SQL Serverなど)を簡単に使用できるようにします。最後に、Unitilsは、APIを近代化し、DBUnitの操作をより快適にするDBUnitのニースラッパーを提供します。
ユニティルをまだチェックアウトしていない場合は、絶対にすべきです。ユニティルはしばしば見過ごされ、過小評価されています。
それほど簡単ではないコードをテストするために、 EasyMock を使用することを好みます。
HSQLがユニットテスト中の方法であると思います。テストのポイントは、jdbcコードをテストして、動作することを確認することです。カスタムクラスを追加するかjdbc呼び出しをモックすると、バグを簡単に隠すことができます。
私は主にmysqlを使用し、テストがドライバークラスを実行し、urlがorg.hsqldb.jdbcDriverおよびjdbc:hsqldb:mem:testに変更されるときに使用します。
統合テストではなく単体テストを実行する場合は、次のように、Mockitoのみを使用して、非常に基本的で単純なアプローチを使用できます。
public class JDBCLowLevelTest {
private TestedClass tested;
private Connection connection;
private static Driver driver;
@BeforeClass
public static void setUpClass() throws Exception {
// (Optional) Print DriverManager logs to system out
DriverManager.setLogWriter(new PrintWriter((System.out)));
// (Optional) Sometimes you need to get rid of a driver (e.g JDBC-ODBC Bridge)
Driver configuredDriver = DriverManager.getDriver("jdbc:odbc:url");
System.out.println("De-registering the configured driver: " + configuredDriver);
DriverManager.deregisterDriver(configuredDriver);
// Register the mocked driver
driver = mock(Driver.class);
System.out.println("Registering the mock driver: " + driver);
DriverManager.registerDriver(driver);
}
@AfterClass
public static void tearDown() throws Exception {
// Let's cleanup the global state
System.out.println("De-registering the mock driver: " + driver);
DriverManager.deregisterDriver(driver);
}
@Before
public void setUp() throws Exception {
// given
tested = new TestedClass();
connection = mock(Connection.class);
given(driver.acceptsURL(anyString())).willReturn(true);
given(driver.connect(anyString(), Matchers.<Properties>any()))
.willReturn(connection);
given(connection.prepareCall(anyString())).willReturn(statement);
}
}
他のMockitoテストのように、さまざまなシナリオをテストできます。
@Test
public void shouldHandleDoubleException() throws Exception {
// given
SomeData someData = new SomeData();
given(connection.prepareCall(anyString()))
.willThrow(new SQLException("Prepare call"));
willThrow(new SQLException("Close exception")).given(connection).close();
// when
SomeResponse response = testClass.someMethod(someData);
// then
assertThat(response, is(SOME_ERROR));
}
アプリケーションでjdbcをモックする方法は、もちろん実際のjdbcトランザクションの実装方法に依存します。
Jdbcをそのまま使用している場合は、DBUtils.getMetadataFor(String tablename)
の行でいくつかのタスクを実行するための一種のユーティリティクラスを自分で作成したと思います。これが意味することは、そのクラスのモックを作成する必要があり、それがあなたが必要とするすべてである可能性があるということです。すでに一連のjdbc関連のモックオブジェクトが利用可能になっているので、これはかなり簡単なソリューションです。私はあなたのjdbcコードがアプリケーション全体で爆発しないと仮定していることに注意してください-もしそうなら、リファクタリング!!!
ただし、データベース処理用のフレームワーク(Spring FrameworkのJDBCテンプレートクラスなど)を使用している場合は、EasyMockまたはその他の同等物を使用してインターフェイスクラスをモックできます。そうすれば、接続を簡単にモックするために必要な世界のすべてのパワーを手に入れることができます。
最後に、他に何も機能しない場合は、他の人がすでに言ったことを実行し、DBUnitやダービーを使用できます。
DBUnit があります。データベースなしでjdbcコードをテストすることはできませんが、データベースをエミュレートすることで別の購入セットを導入できるようです。
Acolyteドライバーを使用して、JDBC接続をモックアップし、テスト中にそれを管理し、結果セットとしてデータを返します(タイプセーフな行リストAPIを使用): https://github.com/cchantep/acolyte
注:私はAcolyteの著者です。
Mockrunnerを使用します。 http://mockrunner.sourceforge.net/ モック接続とデータソースが組み込まれているため、自分で実装する必要はありません。