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:
+ *
+ *
+ * - {@link CreditCardNumber}
+ *
- {@link EAN}
+ *
- {@link Email}
+ *
- {@link Length}
+ *
- {@link LuhnCheck}
+ *
- {@link Mod10Check}
+ *
- {@link Mod11Check}
+ *
- {@link NotBlank}
+ *
- {@link NotEmpty}
+ *
- {@link Range}
+ *
- {@link SafeHtml}
+ *
- {@link URL}
+ *
+ *
* @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;
}
}