diff --git a/build.gradle b/build.gradle index 02b0977a..38edf1e7 100644 --- a/build.gradle +++ b/build.gradle @@ -37,8 +37,9 @@ ext { springVersion = '4.2.5.RELEASE' javadocLinks = [ 'http://docs.oracle.com/javase/8/docs/api/', - "http://docs.spring.io/spring-framework/docs/$springVersion/javadoc-api/", - 'https://docs.jboss.org/hibernate/stable/beanvalidation/api/' + 'http://docs.spring.io/spring-framework/docs/$springVersion/javadoc-api/', + 'https://docs.jboss.org/hibernate/stable/beanvalidation/api/', + 'https://docs.jboss.org/hibernate/stable/validator/api/' ] as String[] } diff --git a/spring-restdocs-core/build.gradle b/spring-restdocs-core/build.gradle index 01ef4b9c..1bee13f5 100644 --- a/spring-restdocs-core/build.gradle +++ b/spring-restdocs-core/build.gradle @@ -34,10 +34,10 @@ dependencies { optional 'commons-codec:commons-codec' optional 'javax.validation:validation-api' optional 'junit:junit' + optional 'org.hibernate:hibernate-validator' testCompile 'org.mockito:mockito-core' testCompile 'org.hamcrest:hamcrest-core' testCompile 'org.hamcrest:hamcrest-library' - testCompile 'org.hibernate:hibernate-validator' testCompile 'org.springframework:spring-test' testRuntime 'org.glassfish:javax.el:3.0.0' } diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/constraints/ResourceBundleConstraintDescriptionResolver.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/constraints/ResourceBundleConstraintDescriptionResolver.java index 759950a6..c55596c3 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/constraints/ResourceBundleConstraintDescriptionResolver.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/constraints/ResourceBundleConstraintDescriptionResolver.java @@ -34,6 +34,19 @@ import javax.validation.constraints.Past; import javax.validation.constraints.Pattern; import javax.validation.constraints.Size; +import org.hibernate.validator.constraints.CreditCardNumber; +import org.hibernate.validator.constraints.EAN; +import org.hibernate.validator.constraints.Email; +import org.hibernate.validator.constraints.Length; +import org.hibernate.validator.constraints.LuhnCheck; +import org.hibernate.validator.constraints.Mod10Check; +import org.hibernate.validator.constraints.Mod11Check; +import org.hibernate.validator.constraints.NotBlank; +import org.hibernate.validator.constraints.NotEmpty; +import org.hibernate.validator.constraints.Range; +import org.hibernate.validator.constraints.SafeHtml; +import org.hibernate.validator.constraints.URL; + import org.springframework.util.PropertyPlaceholderHelper; import org.springframework.util.PropertyPlaceholderHelper.PlaceholderResolver; @@ -62,6 +75,24 @@ import org.springframework.util.PropertyPlaceholderHelper.PlaceholderResolver; *
  • {@link Size} * * + *

    + * Default descriptions are also provided for Hibernate Validator's constraints: + * + *

    + * * @author Andy Wilkinson */ public class ResourceBundleConstraintDescriptionResolver diff --git a/spring-restdocs-core/src/test/java/org/springframework/restdocs/constraints/ConstraintDescriptionsTests.java b/spring-restdocs-core/src/test/java/org/springframework/restdocs/constraints/ConstraintDescriptionsTests.java index 34e916c5..70c0d1ab 100644 --- a/spring-restdocs-core/src/test/java/org/springframework/restdocs/constraints/ConstraintDescriptionsTests.java +++ b/spring-restdocs-core/src/test/java/org/springframework/restdocs/constraints/ConstraintDescriptionsTests.java @@ -16,28 +16,17 @@ package org.springframework.restdocs.constraints; -import java.math.BigDecimal; -import java.util.Date; - -import javax.validation.constraints.AssertFalse; -import javax.validation.constraints.AssertTrue; -import javax.validation.constraints.DecimalMax; -import javax.validation.constraints.DecimalMin; -import javax.validation.constraints.Digits; -import javax.validation.constraints.Future; -import javax.validation.constraints.Max; -import javax.validation.constraints.Min; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Null; -import javax.validation.constraints.Past; -import javax.validation.constraints.Pattern; -import javax.validation.constraints.Size; +import java.util.Arrays; +import java.util.Collections; import org.junit.Test; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.Matchers.contains; -import static org.hamcrest.Matchers.hasSize; import static org.junit.Assert.assertThat; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; /** * Tests for {@link ConstraintDescriptions}. @@ -46,152 +35,41 @@ import static org.junit.Assert.assertThat; */ public class ConstraintDescriptionsTests { + private final ConstraintResolver constraintResolver = mock(ConstraintResolver.class); + + private final ConstraintDescriptionResolver constraintDescriptionResolver = mock( + ConstraintDescriptionResolver.class); + private final ConstraintDescriptions constraintDescriptions = new ConstraintDescriptions( - Constrained.class); + Constrained.class, this.constraintResolver, + this.constraintDescriptionResolver); @Test - public void assertFalse() { - assertThat(this.constraintDescriptions.descriptionsForProperty("assertFalse"), - contains("Must be false")); + public void descriptionsForConstraints() { + Constraint constraint1 = new Constraint("constraint1", + Collections.emptyMap()); + Constraint constraint2 = new Constraint("constraint2", + Collections.emptyMap()); + given(this.constraintResolver.resolveForProperty("foo", Constrained.class)) + .willReturn(Arrays.asList(constraint1, constraint2)); + given(this.constraintDescriptionResolver.resolveDescription(constraint1)) + .willReturn("Bravo"); + given(this.constraintDescriptionResolver.resolveDescription(constraint2)) + .willReturn("Alpha"); + assertThat(this.constraintDescriptions.descriptionsForProperty("foo"), + contains("Alpha", "Bravo")); } @Test - public void assertTrue() { - assertThat(this.constraintDescriptions.descriptionsForProperty("assertTrue"), - contains("Must be true")); - } - - @Test - public void decimalMax() { - assertThat(this.constraintDescriptions.descriptionsForProperty("decimalMax"), - contains("Must be at most 9.875")); - } - - @Test - public void decimalMin() { - assertThat(this.constraintDescriptions.descriptionsForProperty("decimalMin"), - contains("Must be at least 1.5")); - } - - @Test - public void digits() { - assertThat(this.constraintDescriptions.descriptionsForProperty("digits"), - contains("Must have at most 2 integral digits and 5 fractional digits")); - } - - @Test - public void future() { - assertThat(this.constraintDescriptions.descriptionsForProperty("future"), - contains("Must be in the future")); - } - - @Test - public void max() { - assertThat(this.constraintDescriptions.descriptionsForProperty("max"), - contains("Must be at most 10")); - } - - @Test - public void min() { - assertThat(this.constraintDescriptions.descriptionsForProperty("min"), - contains("Must be at least 5")); - } - - @Test - public void notNull() { - assertThat(this.constraintDescriptions.descriptionsForProperty("notNull"), - contains("Must not be null")); - } - - @Test - public void nul() { - assertThat(this.constraintDescriptions.descriptionsForProperty("nul"), - contains("Must be null")); - } - - @Test - public void past() { - assertThat(this.constraintDescriptions.descriptionsForProperty("past"), - contains("Must be in the past")); - } - - @Test - public void pattern() { - assertThat(this.constraintDescriptions.descriptionsForProperty("pattern"), - contains("Must match the regular expression `[A-Z][a-z]+`")); - } - - @Test - public void size() { - assertThat(this.constraintDescriptions.descriptionsForProperty("size"), - contains("Size must be between 0 and 10 inclusive")); - } - - @Test - public void sizeList() { - assertThat(this.constraintDescriptions.descriptionsForProperty("sizeList"), - contains("Size must be between 1 and 4 inclusive", - "Size must be between 8 and 10 inclusive")); - } - - @Test - public void unconstrained() { - assertThat(this.constraintDescriptions.descriptionsForProperty("unconstrained"), - hasSize(0)); - } - - @Test - public void nonExistentProperty() { - assertThat(this.constraintDescriptions.descriptionsForProperty("doesNotExist"), - hasSize(0)); + public void emptyListOfDescriptionsWhenThereAreNoConstraints() { + given(this.constraintResolver.resolveForProperty("foo", Constrained.class)) + .willReturn(Collections.emptyList()); + assertThat(this.constraintDescriptions.descriptionsForProperty("foo").size(), + is(equalTo(0))); } private static class Constrained { - @AssertFalse - private boolean assertFalse; - - @AssertTrue - private boolean assertTrue; - - @DecimalMax("9.875") - private BigDecimal decimalMax; - - @DecimalMin("1.5") - private BigDecimal decimalMin; - - @Digits(fraction = 5, integer = 2) - private BigDecimal digits; - - @Future - private Date future; - - @NotNull - private String notNull; - - @Max(10) - private int max; - - @Min(5) - private int min; - - @Null - private String nul; - - @Past - private Date past; - - @Pattern(regexp = "[A-Z][a-z]+") - private String pattern; - - @Size(min = 0, max = 10) - private String size; - - @Size.List({ @Size(min = 1, max = 4), @Size(min = 8, max = 10) }) - private String sizeList; - - @SuppressWarnings("unused") - private String unconstrained; } }