BeanValidatorBuilder { @Nullable public BeanValidator build() { validate(beanClass); if (Classes.instanceFields(beanClass).stream().noneMatch(this::hasValidationAnnotation)) return null; builder = new DynamicInstanceBuilder<>(BeanValidator.class, beanClass.getName() + "$Validator"); String method = validateMethod(beanClass, null); var code = new CodeBuilder().append("public void validate(Object instance, {} errors, boolean partial) {\n", type(ValidationErrors.class)); code.indent(1).append("{}(({}) instance, errors, partial);\n", method, type(beanClass)); code.append('}'); builder.addMethod(code.build()); return builder.build(); } BeanValidatorBuilder(Class<?> beanClass); @Nullable BeanValidator build();  }
@Test void withoutValidationAnnotation() { assertThat(new BeanValidatorBuilder(Bean.class).build()).isNull(); }
@Test void validateMinAnnotation() { assertThatThrownBy(() -> new BeanValidatorBuilder(BeanWithInvalidMinAnnotation.class).build()) .isInstanceOf(Error.class) .hasMessageContaining("@Min must on Number"); }
@Test void validateSizeAnnotation() { assertThatThrownBy(() -> new BeanValidatorBuilder(BeanWithInvalidSizeAnnotation.class).build()) .isInstanceOf(Error.class) .hasMessageContaining("@Size must on String"); }
@Test void validateNotNull() { assertThatThrownBy(() -> new BeanValidatorBuilder(BeanWithDefaultValue.class).build()) .isInstanceOf(Error.class) .hasMessageContaining("field with default value must have @NotNull"); }