(前回の続き)
前回まででようやく、DBアクセスに関するテスト
- テーブルを作成
- データを登録
- テスト対象クラスのインスタンスを作成
- メソッドを実行
- 結果を検証
を実現できた。しかし、とても効率が良いとは言えない。
今回は、springに用意されているテスト用のクラスを確認してみる。
JdbcTestUtils を使う
SQLを実行するために、前回までは JdbcTemplate#execute()
を使っていたが、
これ以外の選択肢についていろいろと試してみようと思う。まずは、JdbcTestUtils
である。これは、spring-test に含まれる機能である。これを使うと前回の例がどのように
書き換えられるか確認しよう。
drop table sample3
create table sample3 (id numeric(3), str varchar(5))
insert into sample3 values (3, 'c')
package jp.sample;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.EncodedResource;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.jdbc.JdbcTestUtils;
import org.junit.runner.RunWith;
import org.junit.*;
import static org.junit.Assert.*;
import static org.hamcrest.CoreMatchers.*;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:applicationContext.xml")
public class JavaDBSample3Test {
@Autowired
JdbcTemplate jdbcTemplate;
@Autowired
JavaDBSample3 obj;
@Before
public void setUp() {
executeScript("/drop.sql", true);
executeScript("/create.sql", false);
}
@Test
public void test() {
executeScript("/insert.sql", false);
List<Map<String,Object>> list = obj.select();
assertThat(list.size(), is(1));
assertThat((BigDecimal)list.get(0).get("ID"), is(BigDecimal.valueOf(3)));
assertThat((String)list.get(0).get("STR"), is("c"));
}
public void executeScript(String file, boolean continueOnError) {
//EncodedResource resource = new EncodedResource(new ClassPathResource(file, getClass()), "UTF-8");
Resource resource = new ClassPathResource(file, getClass());
JdbcTestUtils.executeSqlScript(jdbcTemplate, resource, continueOnError);
}
}
これで一応テスト用のテーブルスクリプトおよびデータを外出しすることができた。
スクリプトは、クラスパスが通っている src/test/resources 配下で管理する。
しかし、このJdbcTestUtilsメソッドはdeprecated となっており、リファレンスマニュアルを見ると代わりに、
ScriptUtils.executeSqlScript()
または、
ResourceDatabasePopulator クラス
を使えとなっている。ScriptUtils は、低レベルっぽいので、ResourceDatabasePopulatorを使ってみよう。
ResourceDatabasePopulator を使う
ResourceDatabasePopulator は JdbcTemplate ではなくConnectionオブジェクトを使うらしい。もしかすると、JdbcTemplate という抽象化オブジェクト自体が古いのかもしれない。
drop table sample3
create table sample3 (id numeric(3), str varchar(5))
insert into sample3 values (3, 'c')
package jp.sample;
import java.math.BigDecimal;
import java.sql.Connection;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceUtils;
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.ContextConfiguration;
import org.junit.runner.RunWith;
import org.junit.*;
import static org.junit.Assert.*;
import static org.hamcrest.CoreMatchers.*;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:applicationContext.xml")
public class JavaDBSample3Test {
@Autowired
JdbcTemplate jdbcTemplate;
@Autowired
JavaDBSample3 obj;
@Before
public void setUp() {
executeScript("/create.sql");
}
@Test
public void test() {
executeScript("/insert.sql");
List<Map<String,Object>> list = obj.select();
assertThat(list.size(), is(1));
assertThat((BigDecimal)list.get(0).get("ID"), is(BigDecimal.valueOf(3)));
assertThat((String)list.get(0).get("STR"), is("c"));
}
public void executeScript(String file) {
Resource resource = new ClassPathResource(file, getClass());
ResourceDatabasePopulator rdp = new ResourceDatabasePopulator();
rdp.addScript(resource);
rdp.setSqlScriptEncoding("UTF-8");
rdp.setIgnoreFailedDrops(true);
rdp.setContinueOnError(false);
Connection conn = DataSourceUtils.getConnection(jdbcTemplate.getDataSource());
rdp.populate(conn);
}
}
JdbcTestUtils との差分も示す
@@ -1,18 +1,18 @@
package jp.sample;
import java.math.BigDecimal;
+import java.sql.Connection;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
-import org.springframework.core.io.support.EncodedResource;
-import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.datasource.DataSourceUtils;
+import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.ContextConfiguration;
-import org.springframework.test.jdbc.JdbcTestUtils;
import org.junit.runner.RunWith;
import org.junit.*;
@@ -32,13 +32,12 @@
@Before
public void setUp() {
- executeScript("/drop.sql", true);
- executeScript("/create.sql", false);
+ executeScript("/create.sql");
}
@Test
public void test() {
- executeScript("/insert.sql", false);
+ executeScript("/insert.sql");
List<Map<String,Object>> list = obj.select();
@@ -47,9 +46,16 @@
assertThat((String)list.get(0).get("STR"), is("c"));
}
- public void executeScript(String file, boolean continueOnError) {
- //EncodedResource resource = new EncodedResource(new ClassPathResource(file, getClass()), "UTF-8");
+ public void executeScript(String file) {
Resource resource = new ClassPathResource(file, getClass());
- JdbcTestUtils.executeSqlScript(jdbcTemplate, resource, continueOnError);
+
+ ResourceDatabasePopulator rdp = new ResourceDatabasePopulator();
+ rdp.addScript(resource);
+ rdp.setSqlScriptEncoding("UTF-8");
+ rdp.setIgnoreFailedDrops(true);
+ rdp.setContinueOnError(false);
+
+ Connection conn = DataSourceUtils.getConnection(jdbcTemplate.getDataSource());
+ rdp.populate(conn);
}
}
ResourceDatabasePopulator を利用した場合、setIgnoreFailedDrops()
のお陰でdropのエラーを無視することができる。そのため、dropとcreateのスクリプトを一つにすることができた。
そういう点では使い勝手がいい。
次回は、結果をbeanで取得する方法を確認する。