package com.github.mygreen.supercsv.io;
import static org.junit.Assert.*;
import static org.assertj.core.api.Assertions.*;
import static com.github.mygreen.supercsv.tool.TestUtils.*;
import java.io.IOException;
import java.io.StringWriter;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.supercsv.exception.SuperCsvException;
import org.supercsv.prefs.CsvPreference;
import org.supercsv.quote.AlwaysQuoteMode;
import com.github.mygreen.supercsv.annotation.DefaultGroup;
import com.github.mygreen.supercsv.builder.BeanMapping;
import com.github.mygreen.supercsv.builder.BeanMappingFactory;
import com.github.mygreen.supercsv.exception.SuperCsvBindingException;
import com.github.mygreen.supercsv.validation.CsvExceptionConverter;
/**
* {@link CsvAnnotationBeanReader}のテスタ
*
* @since 1.2
* @author T.TSUCHIE
*
*/
public class CsvAnnotationBeanWriterTest {
private CsvExceptionConverter exceptionConverter;
@Before
public void setUp() throws Exception {
this.exceptionConverter = new CsvExceptionConverter();
}
/**
* 書き込みのテスト - 正常
*/
@Test
public void testWrite_normal() throws IOException {
// テストデータの作成
final List<SampleNormalBean> list = createNormalData();
StringWriter strWriter = new StringWriter();
CsvAnnotationBeanWriter<SampleNormalBean> csvWriter = new CsvAnnotationBeanWriter<>(
SampleNormalBean.class,
strWriter,
CsvPreference.STANDARD_PREFERENCE,
DefaultGroup.class, SampleNormalBean.WriteGroup.class);
final String[] expectedHeaders = new String[]{
"id",
"数字1", "number2",
"string1", "string2",
"date1", "date2",
"enum1", "列挙型2",
"boolean1", "boolean2"};
final String[] definitionHeaders = csvWriter.getDefinedHeader();
assertThat(definitionHeaders).containsExactly(expectedHeaders);
csvWriter.writeHeader();
csvWriter.flush();
for(SampleNormalBean item : list) {
csvWriter.write(item);
csvWriter.flush();
}
String actual = strWriter.toString();
System.out.println(actual);
String expected = getTextFromFile("src/test/data/test_write_normal.csv", Charset.forName("UTF-8"));
assertThat(actual).isEqualTo(expected);
assertThat(csvWriter.getErrorMessages()).hasSize(0);
csvWriter.close();
}
/**
* 書き込みのテスト - 正常
*/
@Test
public void testWriteAll_normal() throws IOException {
// テストデータの作成
final List<SampleNormalBean> list = createNormalData();
StringWriter strWriter = new StringWriter();
CsvAnnotationBeanWriter<SampleNormalBean> csvWriter = new CsvAnnotationBeanWriter<>(
SampleNormalBean.class,
strWriter,
CsvPreference.STANDARD_PREFERENCE,
DefaultGroup.class, SampleNormalBean.WriteGroup.class);
csvWriter.writeAll(list);
csvWriter.flush();
String actual = strWriter.toString();
System.out.println(actual);
String expected = getTextFromFile("src/test/data/test_write_normal.csv", Charset.forName("UTF-8"));
assertThat(actual).isEqualTo(expected);
assertThat(csvWriter.getErrorMessages()).hasSize(0);
csvWriter.close();
}
/**
* 書き込みのテスト - 追加書き込み
*/
@Test
public void testWriteAll_append() throws IOException {
// テストデータの作成
final List<SampleNormalBean> list = createNormalData();
StringWriter strWriter = new StringWriter();
CsvAnnotationBeanWriter<SampleNormalBean> csvWriter = new CsvAnnotationBeanWriter<>(
SampleNormalBean.class,
strWriter,
CsvPreference.STANDARD_PREFERENCE,
DefaultGroup.class, SampleNormalBean.WriteGroup.class);
csvWriter.writeAll(list);
csvWriter.flush();
// 追加データの作成
final List<SampleNormalBean> append = createNormalData();
final SampleNormalBean bean3 = append.get(0);
bean3.setId(3);
bean3.setNumber1(-98765);
final SampleNormalBean bean4 = append.get(1);
bean4.setId(4);
bean4.setNumber1(0);
csvWriter.writeAll(append);
csvWriter.flush();
String actual = strWriter.toString();
System.out.println(actual);
String expected = getTextFromFile("src/test/data/test_write_append.csv", Charset.forName("UTF-8"));
assertThat(actual).isEqualTo(expected);
assertThat(csvWriter.getErrorMessages()).hasSize(0);
csvWriter.close();
}
/**
* 全件書き込みのテスト - デフォルト設定 - エラーがある場合
* @since 2.0.2
*/
@Test
public void writeAll_error_column() throws IOException {
// テストデータの作成
final List<SampleNormalBean> list = createNormalData();
// データ1
final SampleNormalBean bean1 = list.get(0);
bean1.setNumber1(1_000_000); // 最大値を超える
bean1.setString1(null); // 必須
StringWriter strWriter = new StringWriter();
CsvAnnotationBeanWriter<SampleNormalBean> csvWriter = new CsvAnnotationBeanWriter<>(
SampleNormalBean.class,
strWriter,
CsvPreference.STANDARD_PREFERENCE,
DefaultGroup.class, SampleNormalBean.WriteGroup.class);
try {
csvWriter.writeAll(list);
csvWriter.flush();
fail();
} catch(Exception e) {
assertThat(e).isInstanceOf(SuperCsvBindingException.class);
}
// convert error messages.
List<String> messages = csvWriter.getErrorMessages();
assertThat(messages).hasSize(2)
.contains("[2行, 2列] : 項目「数字1」の値(1,000,000)は、999,999以下の値でなければなりません。"
, "[2行, 4列] : 項目「string1」の値は必須です。");
messages.forEach(System.out::println);
csvWriter.close();
}
/**
* 全件書き込みのテスト - エラーがある場合も処理を続ける
* @since 2.0.2
*/
@Test
public void writeAll_error_column_continueOnError() throws IOException {
// テストデータの作成
final List<SampleNormalBean> list = createNormalData();
// データ1
final SampleNormalBean bean1 = list.get(0);
bean1.setNumber1(1_000_000); // 最大値を超える
bean1.setString1(null); // 必須
StringWriter strWriter = new StringWriter();
CsvAnnotationBeanWriter<SampleNormalBean> csvWriter = new CsvAnnotationBeanWriter<>(
SampleNormalBean.class,
strWriter,
CsvPreference.STANDARD_PREFERENCE,
DefaultGroup.class, SampleNormalBean.WriteGroup.class);
csvWriter.writeAll(list, true);
csvWriter.flush();
String actual = strWriter.toString();
System.out.println(actual);
String expected = getTextFromFile("src/test/data/test_write_error_continue.csv", Charset.forName("UTF-8"));
assertThat(actual).isEqualTo(expected);
// convert error messages.
List<String> messages = csvWriter.getErrorMessages();
assertThat(messages).hasSize(2)
.contains("[2行, 2列] : 項目「数字1」の値(1,000,000)は、999,999以下の値でなければなりません。"
, "[2行, 4列] : 項目「string1」の値は必須です。");
messages.forEach(System.out::println);
csvWriter.close();
}
/**
* 書き込みのテスト - {@link CsvPreference}のカスタマイズ
*/
@Test
public void testWriteAll_custom_preference() throws IOException {
// テストデータの作成
final List<SampleNormalBean> list = createNormalData();
StringWriter strWriter = new StringWriter();
// タブ区切り、改行コード「LF」、必ずダブルクウォートで囲む設定
final CsvPreference preference = new CsvPreference.Builder('\"', '\t', "\n")
.useQuoteMode(new AlwaysQuoteMode())
.build();
CsvAnnotationBeanWriter<SampleNormalBean> csvWriter = new CsvAnnotationBeanWriter<>(
SampleNormalBean.class,
strWriter,
preference,
DefaultGroup.class, SampleNormalBean.WriteGroup.class);
csvWriter.writeAll(list, true);
csvWriter.flush();
String actual = strWriter.toString();
System.out.println(actual);
String expected = getTextFromFile("src/test/data/test_write_tab.csv", Charset.forName("UTF-8"));
assertThat(actual).isEqualTo(expected);
assertThat(csvWriter.getErrorMessages()).hasSize(0);
csvWriter.close();
}
/**
* 書き込みのテスト - 値が不正
*/
@Test
public void testWrite_error_column_value() throws IOException {
// テストデータの作成
final List<SampleNormalBean> list = createNormalData();
// データ1
final SampleNormalBean bean1 = list.get(0);
bean1.setNumber1(1_000_000); // 最大値を超える
bean1.setString1(null); // 必須
StringWriter strWriter = new StringWriter();
BeanMappingFactory mappingFactory = new BeanMappingFactory();
mappingFactory.getConfiguration().setSkipValidationOnWrite(false);
BeanMapping<SampleNormalBean> beanMapping = mappingFactory.create(SampleNormalBean.class,
DefaultGroup.class, SampleNormalBean.WriteGroup.class);
CsvAnnotationBeanWriter<SampleNormalBean> csvWriter = new CsvAnnotationBeanWriter<>(
beanMapping,
strWriter,
CsvPreference.STANDARD_PREFERENCE);
csvWriter.writeHeader();
csvWriter.flush();
try {
for(SampleNormalBean item : list) {
csvWriter.write(item);
csvWriter.flush();
}
fail();
} catch(SuperCsvException e) {
assertThat(e).isInstanceOf(SuperCsvBindingException.class);
// e.printStackTrace();
}
// convert error messages.
List<String> messages = csvWriter.getErrorMessages();
assertThat(messages).hasSize(2)
.contains("[2行, 2列] : 項目「数字1」の値(1,000,000)は、999,999以下の値でなければなりません。"
, "[2行, 4列] : 項目「string1」の値は必須です。");
messages.forEach(System.out::println);
csvWriter.close();
}
/**
* 書き込みのテスト - 制約のチェックをスキップ
*/
@Test
public void testWrite_ignoreValidation() throws IOException {
// テストデータの作成
final List<SampleNormalBean> list = createNormalData();
// データ1
final SampleNormalBean bean1 = list.get(0);
bean1.setNumber1(1_000_000); // 最大値を超える
bean1.setString1(null); // 必須
StringWriter strWriter = new StringWriter();
BeanMappingFactory mappingFactory = new BeanMappingFactory();
mappingFactory.getConfiguration().setSkipValidationOnWrite(true);
BeanMapping<SampleNormalBean> beanMapping = mappingFactory.create(SampleNormalBean.class,
DefaultGroup.class, SampleNormalBean.WriteGroup.class);
CsvAnnotationBeanWriter<SampleNormalBean> csvWriter = new CsvAnnotationBeanWriter<>(
beanMapping,
strWriter,
CsvPreference.STANDARD_PREFERENCE);
csvWriter.writeHeader();
csvWriter.flush();
for(SampleNormalBean item : list) {
csvWriter.write(item);
csvWriter.flush();
}
String actual = strWriter.toString();
System.out.println(actual);
String expected = getTextFromFile("src/test/data/test_write_ignore_constaint.csv", Charset.forName("UTF-8"));
assertThat(actual).isEqualTo(expected);
assertThat(csvWriter.getErrorMessages()).hasSize(0);
csvWriter.close();
}
/**
* 書き込みのテスト - 部分的に書き込む。
*/
@Test
public void testWrite_partial() throws IOException {
// テストデータの作成
final List<SamplePartialBean> list = createPartialData();
StringWriter strWriter = new StringWriter();
CsvAnnotationBeanWriter<SamplePartialBean> csvWriter = new CsvAnnotationBeanWriter<>(
SamplePartialBean.class,
strWriter,
CsvPreference.STANDARD_PREFERENCE,
DefaultGroup.class, SampleNormalBean.WriteGroup.class);
final String[] expectedHeaders = new String[]{
"id",
"数字1", "number2",
"string1", "string2",
"date1", "date2",
"enum1", "列挙型2",
"boolean1", "boolean2"};
final String[] definitionHeaders = csvWriter.getDefinedHeader();
assertThat(definitionHeaders).containsExactly(expectedHeaders);
csvWriter.writeHeader();
csvWriter.flush();
for(SamplePartialBean item : list) {
csvWriter.write(item);
csvWriter.flush();
}
String actual = strWriter.toString();
System.out.println(actual);
String expected = getTextFromFile("src/test/data/test_write_partial.csv", Charset.forName("UTF-8"));
assertThat(actual).isEqualTo(expected);
assertThat(csvWriter.getErrorMessages()).hasSize(0);
csvWriter.close();
}
/**
* 書き込み用のデータを作成する
* @return
*/
private List<SampleNormalBean> createNormalData() {
// テストデータの作成
final List<SampleNormalBean> list = new ArrayList<>();
// データ1
final SampleNormalBean bean1 = new SampleNormalBean();
list.add(bean1);
bean1.setId(1);
bean1.setNumber1(999110);
bean1.setNumber2(10.2d);
bean1.setString1("abcd");
bean1.setString2("12345");
bean1.setDate1(toDate(2000, 1, 1, 0, 1, 2));
bean1.setDate2(toTimestamp(toDate(2000, 2, 3)));
bean1.setEnum1(SampleEnum.RED);
bean1.setEnum2(SampleEnum.RED);
bean1.setBoolean1(true);
bean1.setBoolean2(null);
// データ2
final SampleNormalBean bean2 = new SampleNormalBean();
list.add(bean2);
bean2.setId(2);
bean2.setNumber1(-12);
bean2.setNumber2(null);
bean2.setString1("あいうえお");
bean2.setString2(null);
bean2.setDate1(toDate(2000, 2, 1, 3, 4, 5));
bean2.setDate2(null);
bean2.setEnum1(SampleEnum.BLUE);
bean2.setEnum2(null);
bean2.setBoolean1(false);
bean2.setBoolean2(Boolean.FALSE);
return list;
}
/**
* 部分的なカラムの書き込み用のデータを作成する
* @return
*/
private List<SamplePartialBean> createPartialData() {
// テストデータの作成
final List<SamplePartialBean> list = new ArrayList<>();
// データ1
final SamplePartialBean bean1 = new SamplePartialBean();
list.add(bean1);
bean1.setId(1);
bean1.setNumber1(999110);
bean1.setString1("abcd");
bean1.setDate1(toDate(2000, 1, 1, 0, 1, 2));
bean1.setEnum1(SampleEnum.RED);
bean1.setBoolean1(true);
// データ2
final SamplePartialBean bean2 = new SamplePartialBean();
list.add(bean2);
bean2.setId(2);
bean2.setNumber1(-12);
bean2.setString1("あいうえお");
bean2.setDate1(toDate(2000, 2, 1, 3, 4, 5));
bean2.setEnum1(SampleEnum.BLUE);
bean2.setBoolean1(false);
return list;
}
/**
* テキストファイルを読み込む。
* @param path
* @param charset
* @return
* @throws IOException
*/
private String getTextFromFile(final String path, final Charset charset) throws IOException {
byte[] data = Files.readAllBytes(Paths.get(path));
return new String(data, charset);
}
}