assertの比較元のデータを作る際に利用できそうなので作ってみました。
実際にテーブルが存在しなくてもDbUnitのxml形式でデータを作れば読み込むことができます。
dbunitの部分とreflectionの部分を別のクラスに分けたかったのですが、いずれやることにして取りあえずこのまま公開します。
例のごとくあまりテストはしていません。
使用しているライブラリは下記の通りです。
・commons-lang3-3.2.1.jar
・dbunit-2.4.9.jar
・guava-16.0.1.jar
FlatXmlDataSetLoader.java
package my.junit.util;
import java.io.File;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.net.MalformedURLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.dbunit.dataset.Column;
import org.dbunit.dataset.DataSetException;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.ITable;
import org.dbunit.dataset.ITableMetaData;
import org.dbunit.dataset.xml.FlatXmlDataSetBuilder;
import com.google.common.base.CaseFormat;
public class FlatXmlDataSetLoader {
/**
* 日付用フォーマット
*/
private static final String[] DEFAULT_DATE_FORMATS = {
"yyyy-MM-dd hh:mm:ss.SSS", "yyyy-MM-dd hh:mm:ss", "yyyy-MM-dd" };
/**
* java.util.Date用フォーマット
*/
private String[] dateFormats = null;
/**
* コンストラクタ
*/
public FlatXmlDataSetLoader() {
this.dateFormats = DEFAULT_DATE_FORMATS;
}
/**
* コンストラクタ
*/
public FlatXmlDataSetLoader(String... dateFormats) {
this.dateFormats = dateFormats;
}
/**
* DbUnit用のxmlファイルの1レコード分をMap化したリストを取得します。
*
* @param filePath
* xmlファイルのパス
* @param tableName
* 取得したいテーブル
* @return 1レコード分をMapに設定したリスト
*/
public List<Map<String, Object>> importToMapList(String filePath,
String tableName) {
try {
IDataSet dataSet = new FlatXmlDataSetBuilder().build(new File(
filePath));
ITable table = dataSet.getTable(tableName);
ITableMetaData meta = table.getTableMetaData();
Column[] columns = meta.getColumns();
List<Map<String, Object>> records = new ArrayList<Map<String, Object>>();
for (int i = 0; i < table.getRowCount(); i++) {
Map<String, Object> record = new HashMap<String, Object>();
for (Column column : columns) {
String columnName = column.getColumnName();
record.put(columnName, table.getValue(i, columnName));
}
records.add(record);
}
return records;
} catch (MalformedURLException e) {
throw new IllegalArgumentException(e);
} catch (DataSetException e) {
throw new IllegalArgumentException(e);
}
}
/**
* DbUnit用のxmlファイルの1レコード分をbean化したリストを取得します。
*
* @param filePath
* xmlファイルのパス
* @param tableName
* 取得したいテーブル
* @param beanClass
* 設定対象のbean class
* @return 1レコード分をbeanに設定したリスト
*/
public <B> List<B> importToBeanList(String filePath, String tableName,
Class<B> beanClass) {
List<Map<String, Object>> snakeMapList = importToMapList(filePath,
tableName);
List<Map<String, Object>> camelMapList = new ArrayList<Map<String, Object>>();
for (Map<String, Object> snakeMap : snakeMapList) {
camelMapList.add(convertToLowerCamelKey(snakeMap));
}
return convertMapListToBeanList(camelMapList, beanClass);
}
/**
* Mapのリストをbeanのリストに変換します。
*
* @param mapList
* Mapの
* @param beanClass
* 設定対象のbean class
* @return beanのリスト
*/
public <B> List<B> convertMapListToBeanList(
List<Map<String, Object>> mapList, Class<B> beanClass) {
Map<String, Field> fieldsInfo = getFieldInfo(beanClass);
List<B> beans = new ArrayList<B>();
for (Map<String, Object> map : mapList) {
try {
beans.add(convertMapToBean(map, beanClass.newInstance(),
fieldsInfo));
} catch (InstantiationException e) {
throw new IllegalArgumentException(e);
} catch (IllegalAccessException e) {
throw new IllegalArgumentException(e);
}
}
return beans;
}
/**
* Mapのリストをbeanのリストに変換します。
*
* @param map
* Map
* @param beanClass
* 設定対象のbean class
* @return bean
*/
public <B> B convertMapToBean(Map<String, Object> map, Class<B> beanClass) {
try {
return convertMapToBean(map, beanClass.newInstance());
} catch (InstantiationException e) {
throw new IllegalArgumentException(e);
} catch (IllegalAccessException e) {
throw new IllegalArgumentException(e);
}
}
/**
* Mapのリストをbeanのリストに変換します。
*
* @param map
* Map
* @param bean
* 設定対象のbean
* @return bean
*/
public <B> B convertMapToBean(Map<String, Object> map, B bean) {
Map<String, Field> fieldMap = getFieldInfo(bean.getClass());
return convertMapToBean(map, bean, fieldMap);
}
/**
* Mapのリストをbeanのリストに変換します。
*
* @param map
* Map
* @param bean
* 設定対象のbean
* @param fieldsInfo
* beanのフィールド情報
* @return bean
*/
private <B> B convertMapToBean(Map<String, Object> map, B bean,
Map<String, Field> fieldsInfo) {
Set<Entry<String, Field>> fieldSet = fieldsInfo.entrySet();
for (Entry<String, Field> fieldEntry : fieldSet) {
Field field = fieldEntry.getValue();
Object value = map.get(fieldEntry.getKey());
setFieldValue(bean, field, value);
}
return bean;
}
/**
* クラスのフィールド情報を取得します。
*
* @param beanClass
* 対象のクラス
* @return フィールド名をキーにしたフィールドのマップ
*/
private static Map<String, Field> getFieldInfo(Class<?> beanClass) {
Field[] fields = FieldUtils.getAllFields(beanClass);
Map<String, Field> fieldMap = new HashMap<String, Field>();
for (Field field : fields) {
String key = field.getName();
fieldMap.put(key, field);
}
return fieldMap;
}
/**
* マップのキーをスネークケースからキャメルケースに変換します。
*
* @param snakeMap
* キーがスネークケースのマップ
* @return キーがキャメルケースのマップ
*/
private static <V> Map<String, V> convertToLowerCamelKey(
Map<String, V> snakeMap) {
Map<String, V> camelMap = new HashMap<String, V>();
Set<String> snakeKeys = snakeMap.keySet();
for (String snake : snakeKeys) {
String camel = CaseFormat.UPPER_UNDERSCORE.to(
CaseFormat.LOWER_CAMEL, snake);
camelMap.put(camel, snakeMap.get(snake));
}
return camelMap;
}
/**
* fieldのclassに合わせた形式に変換し値を設定
*
* @param bean
* 設定対象のbean
* @param field
* 設定対象のfield
* @param value
* 設定する値
* @return true:設定完了、false:未設定
*/
private boolean setFieldValue(Object bean, Field field, Object value) {
if (value == null) {
// nullの場合
return false;
}
try {
field.setAccessible(true);
String val = value.toString();
if (field.getType().equals(String.class)) {
field.set(bean, val);
} else if (field.getType().equals(char[].class)) {
field.set(bean, val.toCharArray());
} else if (field.getType().equals(Boolean.class)) {
field.set(bean, new Boolean(val));
} else if (field.getType().equals(boolean.class)) {
field.set(bean, new Boolean(val).booleanValue());
} else if (field.getType().equals(Byte.class)) {
field.set(bean, Byte.valueOf(val));
} else if (field.getType().equals(byte.class)) {
field.set(bean, Byte.valueOf(val).byteValue());
} else if (field.getType().equals(Integer.class)) {
field.set(bean, Integer.valueOf(val));
} else if (field.getType().equals(int.class)) {
field.set(bean, Integer.valueOf(val));
} else if (field.getType().equals(Long.class)) {
field.set(bean, Long.valueOf(val));
} else if (field.getType().equals(long.class)) {
field.set(bean, Long.valueOf(val));
} else if (field.getType().equals(Short.class)) {
field.set(bean, Short.valueOf(val));
} else if (field.getType().equals(short.class)) {
field.set(bean, Short.valueOf(val));
} else if (field.getType().equals(Double.class)) {
field.set(bean, Double.valueOf(val));
} else if (field.getType().equals(double.class)) {
field.set(bean, Double.valueOf(val));
} else if (field.getType().equals(BigDecimal.class)) {
field.set(bean, new BigDecimal(val));
} else if (field.getType().equals(Date.class)) {
field.set(bean, DateUtils.parseDate(val, dateFormats));
} else if (field.getType().equals(Timestamp.class)) {
Date date = DateUtils.parseDate(val, dateFormats);
field.set(bean, new Timestamp(date.getTime()));
} else {
return false;
}
} catch (Exception e) {
throw new IllegalArgumentException(e);
} finally {
field.setAccessible(false);
}
return true;
}
}