package com.github.mygreen.supercsv.validation.beanvalidation;
import static org.junit.Assert.*;
import static org.assertj.core.api.Assertions.*;
import static com.github.mygreen.supercsv.tool.TestUtils.*;
import java.util.List;
import java.util.ResourceBundle;
import java.util.stream.Collectors;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import javax.validation.constraints.AssertTrue;
import javax.validation.constraints.DecimalMax;
import javax.validation.constraints.Pattern;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.NotEmpty;
import org.hibernate.validator.constraints.Range;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
import com.github.mygreen.supercsv.annotation.CsvBean;
import com.github.mygreen.supercsv.annotation.CsvColumn;
import com.github.mygreen.supercsv.builder.BeanMapping;
import com.github.mygreen.supercsv.builder.BeanMappingFactory;
import com.github.mygreen.supercsv.localization.MessageInterpolator;
import com.github.mygreen.supercsv.localization.MessageResolver;
import com.github.mygreen.supercsv.localization.ResourceBundleMessageResolver;
import com.github.mygreen.supercsv.validation.CsvBindingErrors;
import com.github.mygreen.supercsv.validation.CsvExceptionConverter;
import com.github.mygreen.supercsv.validation.ValidationContext;
/**
* {@link CsvBeanValidator}のテスタ
*
* @since 2.0
* @author T.TSUCHIE
*
*/
public class CsvBeanValidatorTest {
@Rule
public TestName name = new TestName();
private CsvBeanValidator csvValidator;
private CsvBeanValidator csvValidatorCustomMessage;
private BeanMappingFactory beanMappingFactory;
private CsvExceptionConverter exceptionConverter;
private final Class<?>[] groupEmpty = new Class[]{};
private MessageResolver testMessageResolver;
private MessageInterpolator messageInterpolator;
@Before
public void setUp() throws Exception {
this.beanMappingFactory = new BeanMappingFactory();
this.exceptionConverter = new CsvExceptionConverter();
this.testMessageResolver = new ResourceBundleMessageResolver(ResourceBundle.getBundle("TestMessages"));
this.messageInterpolator = new MessageInterpolator();
this.csvValidator = new CsvBeanValidator();
final ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
final Validator beanValidator = validatorFactory.usingContext()
.messageInterpolator(new MessageInterpolatorAdapter(testMessageResolver, messageInterpolator))
.getValidator();
this.csvValidatorCustomMessage = new CsvBeanValidator(beanValidator);
}
// テスト用のグループ
private interface Group1 { }
private interface Group2 { }
private interface Group3 { }
private interface Group4 { }
@CsvBean
private static class TestCsv {
@CsvColumn(number=1)
@NotEmpty
private String id;
@CsvColumn(number=2)
@Length(max=10)
@Pattern(regexp="[\\p{Alnum}]+", message="半角英数字で設定してください。", groups=Group1.class)
private String name;
@CsvColumn(number=3)
@Range(min=0, max=100, groups=Group2.class)
private Integer age;
@CsvColumn(number=4)
boolean used;
@AssertTrue(message="{name}が設定されている際には、{age}は必須です。", groups=Group2.class)
boolean isValidAgeRequired() {
if(name != null && !name.isEmpty()) {
return age != null;
}
return false;
}
@DecimalMax(value="20", groups=Group3.class)
Integer getAge() {
return age;
}
@AssertTrue(groups=Group4.class)
boolean isUsed() {
return used;
}
}
/**
* 標準のValidatorの場合
*/
@Test
public void testValidate_default() {
Class<?>[] groups = groupEmpty;
CsvBindingErrors bindingErrors = new CsvBindingErrors(TestCsv.class);
BeanMapping<TestCsv> beanMapping = beanMappingFactory.create(TestCsv.class, groupEmpty);
ValidationContext<TestCsv> validationContext = new ValidationContext<>(ANONYMOUS_CSVCONTEXT, beanMapping);
TestCsv record = new TestCsv();
csvValidator.validate(record, bindingErrors, (ValidationContext)validationContext);
List<String> messages = bindingErrors.getAllErrors().stream()
.map(error -> error.format(testMessageResolver, messageInterpolator))
.collect(Collectors.toList());
assertThat(messages).hasSize(1)
.contains("値が未設定です。");
}
/**
* グループ指定の場合
*/
@Test
public void testValidate_groups() {
Class<?>[] groups = new Class[]{Group1.class};
CsvBindingErrors bindingErrors = new CsvBindingErrors(TestCsv.class);
BeanMapping<TestCsv> beanMapping = beanMappingFactory.create(TestCsv.class, groupEmpty);
ValidationContext<TestCsv> validationContext = new ValidationContext<>(ANONYMOUS_CSVCONTEXT, beanMapping);
TestCsv record = new TestCsv();
record.id = "a01";
record.name = "あいう";
csvValidator.validate(record, bindingErrors, (ValidationContext)validationContext, groups);
List<String> messages = bindingErrors.getAllErrors().stream()
.map(error -> error.format(testMessageResolver, messageInterpolator))
.collect(Collectors.toList());
assertThat(messages).hasSize(1)
.contains("半角英数字で設定してください。");
}
/**
* 相関チェックの場合
*/
@Test
public void testValidate_relation() {
Class<?>[] groups = new Class[]{Group2.class};
CsvBindingErrors bindingErrors = new CsvBindingErrors(TestCsv.class);
BeanMapping<TestCsv> beanMapping = beanMappingFactory.create(TestCsv.class, groupEmpty);
ValidationContext<TestCsv> validationContext = new ValidationContext<>(ANONYMOUS_CSVCONTEXT, beanMapping);
TestCsv record = new TestCsv();
record.id = "a01";
record.name = "test";
csvValidator.validate(record, bindingErrors, (ValidationContext)validationContext, groups);
List<String> messages = bindingErrors.getAllErrors().stream()
.map(error -> error.format(testMessageResolver, messageInterpolator))
.collect(Collectors.toList());
assertThat(messages).hasSize(1)
.contains("名前が設定されている際には、年齢は必須です。");
}
/**
* getterメソッドの場合
*/
@Test
public void testValidate_getter() {
Class<?>[] groups = new Class[]{Group3.class};
CsvBindingErrors bindingErrors = new CsvBindingErrors(TestCsv.class);
BeanMapping<TestCsv> beanMapping = beanMappingFactory.create(TestCsv.class, groupEmpty);
ValidationContext<TestCsv> validationContext = new ValidationContext<>(ANONYMOUS_CSVCONTEXT, beanMapping);
TestCsv record = new TestCsv();
record.id = "a01";
record.name = "test";
record.age = 40;
csvValidator.validate(record, bindingErrors, (ValidationContext)validationContext, groups);
List<String> messages = bindingErrors.getAllErrors().stream()
.map(error -> error.format(testMessageResolver, messageInterpolator))
.collect(Collectors.toList());
assertThat(messages).hasSize(1)
.contains("20以下の値を設定してください。");
}
/**
* getterメソッドの場合 - boolean
*/
@Test
public void testValidate_getter_boolean() {
Class<?>[] groups = new Class[]{Group4.class};
CsvBindingErrors bindingErrors = new CsvBindingErrors(TestCsv.class);
BeanMapping<TestCsv> beanMapping = beanMappingFactory.create(TestCsv.class, groupEmpty);
ValidationContext<TestCsv> validationContext = new ValidationContext<>(ANONYMOUS_CSVCONTEXT, beanMapping);
TestCsv record = new TestCsv();
record.id = "a01";
record.used = false;
csvValidator.validate(record, bindingErrors, (ValidationContext)validationContext, groups);
List<String> messages = bindingErrors.getAllErrors().stream()
.map(error -> error.format(testMessageResolver, messageInterpolator))
.collect(Collectors.toList());
assertThat(messages).hasSize(1)
.contains("trueを設定してください。");
}
/**
* カスタマイズしたValidatorの場合
*/
@Test
public void testValidate_custom() {
Class<?>[] groups = groupEmpty;
CsvBindingErrors bindingErrors = new CsvBindingErrors(TestCsv.class);
BeanMapping<TestCsv> beanMapping = beanMappingFactory.create(TestCsv.class, groupEmpty);
ValidationContext<TestCsv> validationContext = new ValidationContext<>(ANONYMOUS_CSVCONTEXT, beanMapping);
TestCsv record = new TestCsv();
csvValidatorCustomMessage.validate(record, bindingErrors, (ValidationContext)validationContext);
List<String> messages = bindingErrors.getAllErrors().stream()
.map(error -> error.format(testMessageResolver, messageInterpolator))
.collect(Collectors.toList());
assertThat(messages).hasSize(1)
.contains("[2行, 1列] : 項目「id」の値は必須です。");
}
}