import de.huepattl.playground.validation.Employee;
import de.huepattl.playground.validation.Severity;
import de.huepattl.playground.validation.validator.SimpleConstraintValidator;
import de.huepattl.playground.validation.StricterValidationGroup;
import org.junit.Test;
import static org.junit.Assert.*;
import javax.validation.ConstraintViolation;
import javax.validation.groups.Default;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.Month;
import java.sql.Date;
import java.util.Set;
/**
* This test demonstrates how to validate a bean (POJO) that is annotated with the default Java constraint validation
* annotations, such as {@link javax.validation.constraints.NotNull}, {@link javax.validation.constraints.Size}, {@link
* javax.validation.constraints.Digits} etc. We use the default constraint validator as well, so there is no custom
* validator implementation required (except the service facade).
*
* @author Timo Boewing (bjblazko@gmail.com)
* @see de.huepattl.playground.validation.validator.SimpleConstraintValidator
* @since 2014-02-02
*/
public class SimpleConstraintValidatorTest extends AbstractValidationTest {
/**
* Simple constraint test - each bean field valid, so no validation error should be reported.
*
* @throws Exception BAM!
*/
@Test
public void testNoErrors() throws Exception {
/*
* Set up correct bean.
*/
Employee employee = super.newValidBean();
/*
* Validate and report.
*/
SimpleConstraintValidator defaultValidator = new SimpleConstraintValidator();
Set<ConstraintViolation<Object>> validationResult = defaultValidator.validate(employee);
super.printValidationMessages(validationResult);
assertTrue(validationResult.isEmpty());
}
/**
* Simple constraint test - each bean field invalid, so plenty of validation errors should be reported.
*
* @throws Exception BAM!
*/
@Test
public void testFailAll() throws Exception {
/*
* Set up incorrect bean.
*/
Employee employee = new Employee();
{
// Expecting: true.
employee.setActive(false);
// Expecting: Value between 1 and 100, including.
employee.setId(101);
// Expecting: Date in the past, not null.
employee.setDateOfBirth(Date.valueOf(LocalDate.of(9999, Month.DECEMBER, 31)));
// Expecting: Any string between 3 and 50 characters, not null.
employee.setLastName("Only1234andChars... ooops!");
// Expecting: String only consisting of letters and numbers but no special chars, blanks; not null.
employee.setFirstName("Only1234andChars... ooops!");
// Expecting: Between 1..100, no more than 3 digits and 2 fractions, not null.
employee.setSalary(new BigDecimal("2334.0000001"));
// Expecting: Any string with the number 3...
employee.setCheckedByCustomAnnotation("A string with another number: 2 (not three)");
}
/*
* Validate and report.
*/
SimpleConstraintValidator defaultValidator = new SimpleConstraintValidator();
Set<ConstraintViolation<Object>> validationResult = defaultValidator.validate(employee);
super.printValidationMessages(validationResult);
assertFalse(validationResult.isEmpty());
}
/**
* <p>Let us take a look at validation groups. All constraint annotations allow you to explicitly use a certain
* group.
* When not defined, all constraints are active in the default group (=mode) during validation.</p>
* <p>However, sooner or later you will have reason to have seperate scopes/levels of validation. For example, you
* will have to dinstinguish between stricter and lesser strict validation depending on the busniess case. Thus,
* you can apply different validation groups in your annotations and a matching one in the validator.</p>
* <p>Validation groups are just emoty marker interfaces that you can define, no more, no less.</p>
* <p>The validator offers optional group arguments in the {@link javax.validation.Validator#validate(Object,
* Class[])} method.</p>
*
* @throws Exception BAM!
*/
@Test
public void testGroups() throws Exception {
Employee employee = super.newValidBean();
SimpleConstraintValidator defaultValidator = new SimpleConstraintValidator();
Set<ConstraintViolation<Object>> validationResult;
/*
* Validate with implicit default group.
* Expecting NotNull to raise error.
*/
employee.setStricterValueThanOthers(null);
validationResult = defaultValidator.validate(employee);
super.printValidationMessages(validationResult);
assertTrue(validationResult.size() == 1);
/*
* Validate with implicit default group.
* Expecting no issue because value is not null. However, the value is too short but will not be thrown
* because that constraint is only active for the StricterValidationGroup, which is not active here.
*/
employee.setStricterValueThanOthers("A");
validationResult = defaultValidator.validate(employee);
super.printValidationMessages(validationResult);
assertTrue(validationResult.isEmpty());
/*
* Validate with explicit default StricterValidationGroup group.
* Expecting error because value is too short.
*/
employee.setStricterValueThanOthers("A");
validationResult = defaultValidator.validate(employee, StricterValidationGroup.class);
super.printValidationMessages(validationResult);
assertTrue(validationResult.size() == 1);
/*
* Validate with explicit default StricterValidationGroup group.
* Expecting no error because value os long enough.
*/
employee.setStricterValueThanOthers("ABC");
validationResult = defaultValidator.validate(employee, StricterValidationGroup.class);
super.printValidationMessages(validationResult);
assertTrue(validationResult.isEmpty());
/*
* Validate with explicit default StricterValidationGroup group.
* Expecting NotNull NOT to fire because it is in the default group
* and thus does not apply.
*/
employee.setStricterValueThanOthers(null); //notnull does not apply!
validationResult = defaultValidator.validate(employee, StricterValidationGroup.class);
super.printValidationMessages(validationResult);
assertTrue(validationResult.isEmpty());
/*
* Validate with default and StricterValidationGroup groups.
* Expecintg NotNull to apply because we now took the default group back into the game.
*/
employee.setStricterValueThanOthers(null); //notnull does not apply!
validationResult = defaultValidator.validate(employee, Default.class, StricterValidationGroup.class);
super.printValidationMessages(validationResult);
assertTrue(validationResult.size() == 1);
}
/**
* Java Bean Validation has no direct support for defining severity levels. However, there is the possibility of
* using the {@link javax.validation.Payload} attribute of a constraint annotation and define a custom-made
* severity
* level there. In order to do so, your severity has ti implement {@link javax.validation.Payload}.
*
* @throws Exception BAM!
* @see de.huepattl.playground.validation.Severity
*/
@Test
public void testSeverity() throws Exception {
Employee employee = super.newValidBean();
employee.setUsingSeverity("A"); // too short
boolean foundWarning = false;
SimpleConstraintValidator defaultValidator = new SimpleConstraintValidator();
Set<ConstraintViolation<Object>> validationResult = defaultValidator.validate(employee);
for (final ConstraintViolation cv : validationResult) {
foundWarning = cv.getConstraintDescriptor().getPayload().contains(Severity.WARNING.class);
}
assertTrue(foundWarning);
}
}