DBのユニットテスト② Java

前回の続きです。
userテーブルに対応するBeanとDaoを作ってみます。

User.java

userテーブルと同じ構成のBeanです。
toString()とequals()はApache Commons Langを使うと楽に実装できます。

package sample;

import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;

public class User {

  private int id;
  private String name;

  public User() {
  }

  public User(int id, String name) {
    this.id = id;
    this.name = name;
  }

  public int getId() {
    return this.id;
  }

  public void setId(int id) {
    this.id = id;
  }

  public String getName() {
    return this.name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public String toString() {
      return ToStringBuilder.reflectionToString(this);
  }

  public boolean equals(Object obj) {
      return EqualsBuilder.reflectionEquals(this, obj);
  }

}

UsrDao.java

DaoはなんとなくApache Commons dbutilsで実装してみました。
SQLベースなので、個人的にdbutilsは好みです。


userテーブルに対して、
SELECT/INSERT/UPDATE/DELETEするメソッドを実装しておきます。

package sample;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;

public class UserDao {

  private Connection con;
  private QueryRunner qr = new QueryRunner();

  public UserDao(Connection con) {
    this.con = con;
  }

  public List<User> selectAll() throws SQLException {
    BeanListHandler<User> handler = new BeanListHandler<User>(User.class);
    return (List<User>) this.qr.query(con, "SELECT * FROM user ORDER BY id ASC", handler);
  }

  public User select(int id) throws SQLException {
    Object[] params = new Object[] { id };
    BeanHandler<User> handler = new BeanHandler<User>(User.class);
    return (User) this.qr.query(con, "SELECT * FROM user WHERE id = ?", handler, params);
  }

  public void insert(User user) throws SQLException {
    Object[] params = new Object[] { user.getId(), user.getName() };
    this.qr.update(con, "INSERT INTO user(id,name) VALUES(?,?)", params);
  }

  public void update(User user) throws SQLException {
    Object[] params = new Object[] { user.getName(), user.getId() };
    this.qr.update(con, "UPDATE user SET name = ? WHERE id = ?", params);
  }

  public void delete(int id) throws SQLException {
    Object[] params = new Object[] { id };
    this.qr.update(con, "DELETE FROM user WHERE id = ?", params);
  }
}




UserDaoのテストクラス作成を簡単にする為に、ユーティリティクラスも作ってみます。

Dbcp.java

DBコネクションを管理するクラスです。
Apache Commons DBCPでコネクションプーリングします。
DB接続情報はdbcp.propertiesで外出しにしておきます。

package sample;

import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.commons.dbcp.BasicDataSourceFactory;

public class Dbcp {

  private static Dbcp instance;
  private DataSource ds;

  public static Dbcp getInstance() throws Throwable {
    if (Dbcp.instance == null) {
      Dbcp.instance = new Dbcp();
    }
    return Dbcp.instance;
  }

  private Dbcp() throws Throwable {
    Properties properties = new Properties();
    properties.load(new FileInputStream("dbcp.properties"));
    this.ds = BasicDataSourceFactory.createDataSource(properties);
  }

  public Connection getConnection() throws SQLException {
    return this.ds.getConnection();
  }

}

dbcp.properties

DB接続情報の他に、コネクションプーリングに関する設定が記述できます。
今回はサンプルなんで設定値は適当です(;´Д`)

driverClassName=org.h2.Driver
url=jdbc:h2:tcp://XXX.XXX.XXX.XXX/~/test
username=sa
password=
# オートコミットモード
defaultAutoCommit=false
# コネクションプールの初期コネクション数
initialSize=5
# 最大コネクション数
maxActive=10
# アイドル状態(未使用状態)の最大コネクション数
maxIdle=10
# コネクション取得の待ち時間
maxWait=5000
# コネクションが利用可能か検証するためのSQL
validationQuery=select count(*) from dual

DbTester.java

DBの初期値設定とアサートを行うクラスです。
DbUnitを使うと数行で実装できてしまいますね。
テストデータはExcelファイルで用意するのでApache POIが必要になります。


initDbメソッドで、ExcelファイルのデータをDBへ投入し、
assertDbメソッドで、ExcelファイルのデータとDBのデータを比較します。

package sample;

import java.io.File;
import java.sql.Connection;

import org.dbunit.Assertion;
import org.dbunit.database.DatabaseConnection;
import org.dbunit.database.IDatabaseConnection;
import org.dbunit.dataset.excel.XlsDataSet;
import org.dbunit.operation.DatabaseOperation;

public class DbTester {

  private IDatabaseConnection connection;

  public void setUp(Connection conn) throws Throwable {
    this.connection = new DatabaseConnection(conn);
  }

  public void tearDown() throws Throwable {
    this.connection.close();
  }

  public void initDb(String xlsFilePath) throws Throwable {
    XlsDataSet dataset = new XlsDataSet(new File(xlsFilePath));
    DatabaseOperation.CLEAN_INSERT.execute(this.connection, dataset);
  }

  public void assertDb(String xlsFilePath) throws Throwable {
    XlsDataSet expected = new XlsDataSet(new File(xlsFilePath));
    Assertion.assertEquals(expected, this.connection.createDataSet(expected.getTableNames()));
  }

}