8
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Java + Spring によるテストデータ管理(3)

Posted at

(前回の続き)

前回まででようやく、DBアクセスに関するテスト

  • テーブルを作成
  • データを登録
  • テスト対象クラスのインスタンスを作成
  • メソッドを実行
  • 結果を検証

を実現できた。しかし、とても効率が良いとは言えない。

今回は、springに用意されているテスト用のクラスを確認してみる。

JdbcTestUtils を使う

SQLを実行するために、前回までは JdbcTemplate#execute() を使っていたが、
これ以外の選択肢についていろいろと試してみようと思う。まずは、JdbcTestUtils
である。これは、spring-test に含まれる機能である。これを使うと前回の例がどのように
書き換えられるか確認しよう。

src/test/resources/drop.sql
drop table sample3
src/test/resources/create.sql
create table sample3 (id numeric(3), str varchar(5))
src/test/resources/insert.sql
insert into sample3 values (3, 'c')
src/test/java/jp/sample/JavaDBSample3Test.java
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 という抽象化オブジェクト自体が古いのかもしれない。

src/test/resources/create.sql
drop table sample3
create table sample3 (id numeric(3), str varchar(5))
src/test/resources/insert.sql
insert into sample3 values (3, 'c')
src/test/java/jp/sample/JavaDBSample3Test.java
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で取得する方法を確認する。

8
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?