Validação Javax BigDecimal

Validação Javax BigDecimal

1. Introdução

No tutorialJava Bean Validation Basics, vimos como aplicar a validaçãojavax básica a vários tipos e, neste tutorial, vamos nos concentrar no uso da validaçãojavax comBigDecimal.

2. Validando instâncias deBigDecimal

Infelizmente,with BigDecimal, we can’t use the classic @Min or @Max javax annotations.

Felizmente, temos um conjunto dedicado de anotações para trabalhar com eles:

  • @DecimalMin

  • @Digits

  • @DecimalMax

Vamos ver nossa classeInvoice, que tem um campo do tipoBigDecimal:

public class Invoice {

    @DecimalMin(value = "0.0", inclusive = false)
    @Digits(integer=3, fraction=2)
    private BigDecimal price;
    private String description;

    public Invoice(BigDecimal price, String description) {
        this.price = price;
        this.description = description;
    }
}

2.1. @DecimalMin

The annotated element must be a number whose value is higher or equal to the specified minimum.@DecimalMin tem um atributoinclusive que indica se o valor mínimo especificado é inclusivo ou exclusivo.

2.2. @DecimalMax

@DecimalMax é a contrapartida de@DecimalMin. O elemento anotado deve ser um número cujo valor seja menor ou igual ao máximo especificado. @DecimalMax tem um atributoinclusive que especifica se o valor máximo especificado é inclusivo ou exclusivo.

Além disso,@Min e@Max aceitam apenas valoreslong. Em@DecimalMine@DecimalMax, podemos especificar o valor no formatostring, que pode ser de qualquer tipo numérico.

2.3. @Digits

Em muitos casos, precisamos validar o número de dígitos na parteintegralefraction parte de um númerodecimal.

O@Digit annotation has two attributes, integer and fraction, for specifying the number of allowed digits na parteintegrale partefraction do número.

De acordo comofficial documentation,integer nos permite especificarmaximum number of integral digits accepted for this number. Mas isso é verdade apenas para números não decimais. Para númerosdecimal, ele verifica o número exato de dígitos em uma parteintegral do número. Veremos isso em nosso caso de teste.

Da mesma forma, o atributofraction nos permite especificar omaximum number of fractional digits accepted for this number.

2.4. Casos de teste

Vamos ver essas anotações em ação.

Primeiro, vamos adicionar um teste que cria uma fatura com um preço inválido de acordo com nossa validação e verifica se a validação irá falhar:

public class InvoiceUnitTest {

    private static Validator validator;

    @BeforeClass
    public static void setupValidatorInstance() {
        validator = Validation.buildDefaultValidatorFactory().getValidator();
    }

    @Test
    public void whenPriceIntegerDigitLessThanThreeWithDecimalValue_thenShouldGiveConstraintViolations() {
        Invoice invoice = new Invoice(new BigDecimal(10.21), "Book purchased");

        Set> violations = validator.validate(invoice);

        assertThat(violations.size()).isEqualTo(1);
        violations.forEach(action -> assertThat(action.getMessage())
                .isEqualTo("numeric value out of bounds (<3 digits>.<2 digits> expected)"));
    }
}

Agora vamos verificar a validação com um preço correto que é um valor inteiro:

@Test
public void whenPriceIntegerDigitLessThanThreeWithIntegerValue_thenShouldNotGiveConstraintViolations() {
    Invoice invoice = new Invoice(new BigDecimal(10), "Book purchased");

    Set> violations = validator.validate(invoice);

    assertThat(violations.size()).isEqualTo(0);
}

Se definirmos um preço com mais de 3 dígitos na parte integrante, veremos um erro de validação:

@Test
public void whenPriceIntegerDigitGreaterThanThree_thenShouldGiveConstraintViolations() {
    Invoice invoice = new Invoice(new BigDecimal(1021.21), "Book purchased");

    Set> violations = validator.validate(invoice);

    assertThat(violations.size()).isEqualTo(1);
    violations.forEach(action -> assertThat(action.getMessage())
      .isEqualTo("numeric value out of bounds (<3 digits>.<2 digits> expected)"));
}

Um preço igual a 000,00 também deve ser uma validação de restrição:

@Test
public void whenPriceIsZero_thenShouldGiveConstraintViolations() {
    Invoice invoice = new Invoice(new BigDecimal(000.00), "Book purchased");

    Set> violations = validator.validate(invoice);

    assertThat(violations.size()).isEqualTo(1);
    violations.forEach(action -> assertThat(action.getMessage())
      .isEqualTo("must be greater than 0.0"));
}

Finalmente, vamos ao caso de um preço maior que 0:

@Test
public void whenPriceIsGreaterThanZero_thenShouldNotGiveConstraintViolations() {
    Invoice invoice = new Invoice(new BigDecimal(100.50), "Book purchased");

    Set> violations = validator.validate(invoice);

    assertThat(violations.size()).isEqualTo(0);
}

3. Conclusão

Neste artigo, vimos como usar a validaçãojavax para BigDecimal.

Todos os trechos de código podem ser encontradosover on GitHub.